我在我的JSON响应中看到一个奇怪的问题,我从资源中检索一个集合,给定资源的ID:数字(可能列表索引?)在之前或之前显示在JSON对象之后。
[
{
"id": 1,
"dateCreated": [
2015,
9,
23,
18,
9,
33,
23000000
],
"dateModified": [
2015,
9,
23,
18,
9,
33,
23000000
],
"name": "First Check-In",
"description": null,
"qualifyingPeriodStartDate": [
2015,
9,
1,
0,
0
],
"customers": [],
"campaign": {
"id": 1,
"dateCreated": [
2015,
9,
24,
14,
59,
31,
474000000
],
"dateModified": [
2015,
9,
24,
14,
59,
31,
474000000
],
"name": "Background campaign",
"startDate": [
2015,
9,
1,
0,
0
],
"endDate": [
2016,
9,
1,
0,
0
],
"chain": null,
"surveys": [],
"achievements": [
1,
{
"id": 2,
"dateCreated": [
2015,
9,
23,
18,
10,
21,
341000000
],
"dateModified": [
2015,
9,
23,
18,
10,
21,
341000000
],
"name": "First Survey Completion",
"description": null,
"qualifyingPeriodStartDate": [
2015,
9,
1,
0,
0
],
"customers": [],
"campaign": 1,
"reward": {
"id": 1,
"dateCreated": [
2015,
9,
24,
14,
59,
31,
815000000
],
"dateModified": [
2015,
9,
24,
14,
59,
31,
815000000
],
"name": "McFlurry",
"customer": null,
"rewardPointValue": 0,
"chain": null,
"achievements": [
1,
2,
{
"id": 3,
"dateCreated": [
2015,
9,
23,
18,
10,
29,
691000000
],
"dateModified": [
2015,
9,
23,
18,
10,
29,
691000000
],
"name": "First Three Check-Ins",
"description": null,
"qualifyingPeriodStartDate": [
2015,
9,
8,
0,
0
],
"customers": [],
"campaign": {
"id": 2,
"dateCreated": [
2015,
9,
24,
14,
59,
31,
782000000
],
"dateModified": [
2015,
9,
24,
14,
59,
31,
782000000
],
"name": "September campaign",
"startDate": [
2015,
9,
11,
0,
0
],
"endDate": [
2015,
9,
18,
0,
0
],
"chain": null,
"surveys": [],
"achievements": [
3
],
"locations": []
},
"reward": 1,
"numActionsRequired": 3,
"actionType": "check-in",
"customerActions": []
}
]
},
"numActionsRequired": 1,
"actionType": "survey-completion",
"customerActions": []
}
],
"locations": []
},
"reward": 1,
"numActionsRequired": 1,
"actionType": "check-in",
"customerActions": []
},
2
]
任何人都可以提供一些有关为什么会发生这种情况的见解,以及如何摆脱这些数字?对于它的价值,我使用Spring with Hibernate和jackson-datatype-hibernate模块。 (https://github.com/FasterXML/jackson-datatype-hibernate)
我也使用@JsonIdentityInfo注释而不是@JsonManagedReference和@JsonBackReference。
父实体:
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQuery(name = "Campaign.byId", query = "from Campaign where id=:id")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Campaign.class)
public class Campaign extends NamedEntity {
private static final long serialVersionUID = 1781401593603214034L;
private LocalDateTime startDate = LocalDateTime.now();
private LocalDateTime endDate = LocalDateTime.now();
@ManyToOne
@JoinColumn(name = "chain_id")
private Chain chain;
@ManyToMany(mappedBy = "campaigns", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Survey> surveys = new ArrayList<Survey>();
@OneToMany(mappedBy = "campaign", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Achievement> achievements = new ArrayList<Achievement>();
@ManyToMany(mappedBy = "campaigns", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Location> locations = new ArrayList<Location>();
private boolean runsIndefinitely;
子实体:
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQueries({ @NamedQuery(name = "Achievement.byId", query = "from Achievement where id=:id"),
@NamedQuery(name = "EligibleAchievements.byCustomerActionId", query = "from Achievement a where :customerActionId not in (select ca.id from a.customerActions as ca) and :customerId not in (select c.id from a.customers as c)"),
@NamedQuery(name = "CountedAchievements.byCustomerActionId", query = "from Achievement a where :id in (select ca.id from a.customerActions as ca)") })
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Achievement.class)
public class Achievement extends NamedEntity {
private static final long serialVersionUID = -8317978091374706947L;
private String description;
private LocalDateTime qualifyingPeriodStartDate = LocalDateTime.now();
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "customers_achievements", joinColumns = @JoinColumn(name = "achievement_id") , inverseJoinColumns = @JoinColumn(name = "customer_id") )
private List<Customer> customers = new ArrayList<Customer>();
@ManyToOne
@JoinColumn(name = "campaign_id")
private Campaign campaign;
@ManyToOne
@JoinColumn(name = "reward_id")
private Reward reward;
private int numActionsRequired;
private String actionType;
@ManyToMany(mappedBy = "achievements", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CustomerAction> customerActions = new ArrayList<CustomerAction>();
我正在从此服务端点方法中检索属于特定广告系列的所有成就:
@RequestMapping(value = "{id}/achievements", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public List<Achievement> getAchievementsFromCampaign(@PathVariable int id) {
List<Achievement> achievements = campaignService.getCampaignAchievements(id);
return achievements;
}
似乎如果我在对父实体(Campaign)的引用上使用JsonIgnore注释,那么数字将替换为我期望的其他JSON对象。我想这是为了防止重复数据显示在JSON响应中。
因此,数字实际上是引用第一个嵌套的Achievement JSON对象中已列出的其他Achievement对象的对象ID。
答案 0 :(得分:0)
似乎答案是将JSON身份引用始终设置为true;见https://fasterxml.github.io/jackson-annotations/javadoc/2.1.0/com/fasterxml/jackson/annotation/JsonIdentityReference.html。
父实体:
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQuery(name = "Campaign.byId", query = "from Campaign where id=:id")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Campaign.class)
public class Campaign extends NamedEntity {
@OneToMany(mappedBy = "campaign", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JsonIdentityReference(alwaysAsId=true)
private List<Achievement> achievements = new ArrayList<Achievement>();
子实体:
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQueries({ @NamedQuery(name = "Achievement.byId", query = "from Achievement where id=:id"),
@NamedQuery(name = "EligibleAchievements.byCustomerActionId", query = "from Achievement a where :customerActionId not in (select ca.id from a.customerActions as ca) and :customerId not in (select c.id from a.customers as c)"),
@NamedQuery(name = "CountedAchievements.byCustomerActionId", query = "from Achievement a where :id in (select ca.id from a.customerActions as ca)") })
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Achievement.class)
public class Achievement extends NamedEntity {
@ManyToOne
@JoinColumn(name = "campaign_id")
@JsonIdentityReference(alwaysAsId=true)
private Campaign campaign;
产生的JSON响应:
[
{
"id": 1,
"dateCreated": [
2015,
9,
23,
18,
9,
33,
23000000
],
"dateModified": [
2015,
9,
23,
18,
9,
33,
23000000
],
"name": "First Check-In",
"description": null,
"qualifyingPeriodStartDate": [
2015,
9,
1,
0,
0
],
"customers": [],
"campaign": 1,
"reward": {
"id": 1,
"dateCreated": [
2015,
9,
24,
15,
12,
37,
188000000
],
"dateModified": [
2015,
9,
24,
15,
12,
37,
188000000
],
"name": "McFlurry",
"customer": null,
"rewardPointValue": 0,
"chain": null,
"achievements": [
1,
2,
3
]
},
"numActionsRequired": 1,
"actionType": "check-in",
"customerActions": []
},
{
"id": 2,
"dateCreated": [
2015,
9,
23,
18,
10,
21,
341000000
],
"dateModified": [
2015,
9,
23,
18,
10,
21,
341000000
],
"name": "First Survey Completion",
"description": null,
"qualifyingPeriodStartDate": [
2015,
9,
1,
0,
0
],
"customers": [],
"campaign": 1,
"reward": 1,
"numActionsRequired": 1,
"actionType": "survey-completion",
"customerActions": []
},
{
"id": 3,
"dateCreated": [
2015,
9,
23,
18,
10,
29,
691000000
],
"dateModified": [
2015,
9,
23,
18,
10,
29,
691000000
],
"name": "First Three Check-Ins",
"description": null,
"qualifyingPeriodStartDate": [
2015,
9,
8,
0,
0
],
"customers": [],
"campaign": 2,
"reward": 1,
"numActionsRequired": 3,
"actionType": "check-in",
"customerActions": []
}
]