Managing circular dependency in JSON response - json

How do I handle the dependency between the two entities? I want to be able to get the games for a player and also players for a game. I am currently trying to do it with #JsonIdentityInfo but the result is not satisfying.
#Entity
#Table(name = "player", uniqueConstraints = { #UniqueConstraint(columnNames = "id") })
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Player.class)
public class Player{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "games_admins", joinColumns = { #JoinColumn(name = "player_id") }, inverseJoinColumns = {
#JoinColumn(name = "game_id") })
private Set<Game> games;
#Entity
#Table(name = "game", uniqueConstraints = { #UniqueConstraint(columnNames = "id") })
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Game.class)
public class Game{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(mappedBy = "games")
private Set<Player> players;
So when I send a GET request to get all of the players I want to receive something like this
[
{
"id": 1,
"name": "Player1",
"games": [
{
"id": 1,
"name": "game1",
"players": [1, 2, 3]
},
{
"id": 2,
"name": "game2",
"players": [1, 3]
},
{
"id": 3,
"name": "game3",
"players": [1, 2]
}
]
},
{
"id": 2,
"name": "Player2",
"games": [
{
"id": 1,
"name": "game1",
"players": [1, 2, 3]
},
{
"id": 3,
"name": "game3",
"players": [1, 2]
}
]
},
{
"id": 3,
"name": "Player3",
"games": [
{
"id": 1,
"name": "game1",
"players": [1, 2, 3]
},
{
"id": 2,
"name": "game2",
"players": [1, 3]
}
]
}
]
So when we reach the "player" again we don't list the games but their ids to avoid the recursion. Same should apply for games.
But what I get is this:
[
{
"id": 1,
"name": "Player1",
"games": [
{
"id": 2,
"name": "game2",
"players": [
1,
{
"id": 3,
"name": "Player3",
"games": [
2,
{
"id": 1,
"name": "game1",
"players": [
{
"id": 2,
"name": "Player2",
"games": [
1,
{
"id": 3,
"name": "game3",
"players": [2, 1]
}
]
},
1,
3
]
}
]
}
]
},
1,
3
]
},
2,
3
]

Related

How to save list of nested two separate objects

How to write model class and establish relation between classes. To save and update the below the JSON using spring boot.
inputJSON
{
"modelName": "",
"modelDescription": "",
"recordStatus": true,
"details": [
{
"tMemberDetail": {
"param1": "",
"pn": {
"param1": "",
"param2": ""
},
"an": {
"param1": "",
"param2": ""
},
"p": {
"h": {
"param1": "",
"param2": ""
},
"v": {
"param1": "",
"param2": ""
},
"r": {
"param1": "",
"param2": ""
}
},
"t": {
"param1": ""
}
},
"mattributes": {
"param1": "",
"SP": {
"param1": "",
"param2": ""
},
"EP": {
"param1": "",
"param2": ""
},
"F": {
"Required": false,
"FT": "",
"G": {
"param1": ""
},
"FP": {
"param1": "",
"param2": ""
},
"Pmr": {
"Required": false,
"Details": {
"param1": "",
"param2": ""
}
},
"Pnt": {
"Required": false,
"Details": {
"param1": "",
"param2": ""
}
},
"ASS": {
"Required": false,
"Details": {
"param1": ""
}
},
"NPA": {
"Required": false,
"Details": {
"param1": "",
"param2": ""
}
}
},
"Start": {
"param1": "",
"Loads": {
"param1": ""
}
},
"End": {
"param1": "",
"Loads": {
"param1": ""
}
}
}
}
]
}
I have tried to achieve by writing model class like below
#Setter
#Getter
#ToString
#Entity
#NoArgsConstructor
public class Model extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long modelId;
private String modelName;
private String modelDescription;
private RecordStatus recordStatus=RecordStatus.ACTIVE;
}
#Setter
#Getter
#Entity
#NoArgsConstructor
public class TModel extends Model implements Serializable{
private static final long serialVersionUID = 7331603514610649855L;
#OneToMany(cascade = CascadeType.ALL , orphanRemoval = true)
private List<TMember > tMembers ;
}
#Setter
#Getter
#ToString
#Entity
#NoArgsConstructor
public class TMember implements Serializable{
private static final long serialVersionUID = 7331603514610649855L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long tMemberId;
#OneToOne(cascade = CascadeType.ALL , orphanRemoval = true)
private TMemberDetail tMemberDetail;
#OneToOne(cascade = CascadeType.ALL , orphanRemoval = true)
private MemberAttribute memberAttributes;
}
The problem I am facing here is that every time I update call child objects, auto incremental id's are incremented by 1.
If I call get service from another application I get only
modelName, modelDescription, recordStatus but not the entire data.

Convert two dimentional array into the json object in Laravel

I am converting a two-dimensional array into a JSON object.
Now my controller returning this output:
[
[
{
"id": 1,
"title": "V1",
"project_id": 1
}
],
[]
]
Want to convert it like:
[
{
"id": 1,
"name": "Laravel"
},
{
"id": 2,
"name": "Wordpress"
}
]
My controller code:
$user = auth()->user();
$projectVersions = array();
foreach($user->projects as $project)
{
$projectId = $project->pivot->project_id;
$projectVersions[] = Version::where('project_id', $projectId)
->where('created_by', $user->id)
->get();
}
return $projectVersions;
When I am using below code which is suggested by #John Lobo, it is returning below output:
{
"id": 2,
"name": "Hadayat Niazi",
"email": "niazicr801#gmail.com",
"is_admin": 0,
"email_verified_at": null,
"created_at": "2021-06-11T15:13:00.000000Z",
"updated_at": "2021-06-11T15:13:00.000000Z",
"projects": [
{
"id": 1,
"name": "Laravel",
"pivot": {
"user_id": 2,
"project_id": 1
},
"versions": [
{
"id": 1,
"title": "V1"
}
]
}
]
}
Displaying the user projects and versions:
Again I am updating the code for #John Lobo, he want to look the output
$user = User::with(['projects', 'projects.versions'])
->find(auth()->user()->id);
$result = $user->projects->map(function ($project) {
return [
$project->versions,
];
});
return $result;
Output the code
[
[
[
{
"id": 1,
"title": "V1",
"project_id": 1,
"version": "1.22",
"created_by": 2,
"is_publish": 0,
"feature": "<b>In this ipdate asdsdasd</b>",
"bug_fix": "<p><b>sdfdffffffffff</b></p>",
"created_at": "2021-06-12T08:08:21.000000Z",
"updated_at": "2021-06-12T08:08:21.000000Z"
},
{
"id": 2,
"title": "v2",
"project_id": 1,
"version": "2.12",
"created_by": 2,
"is_publish": 0,
"feature": "adsdasdsadas",
"bug_fix": "sddasdas",
"created_at": null,
"updated_at": null
}
]
],
[
[]
]
]
In controller you can do the following.if you have relation in project model called version
$projectVersions=User::with(['projects','projects.version'])->find(auth()->user()->id);
return $projectVersions->projects;
I believe Project model has below relationship
public function version(){
return $this->hasMany(Version::class);
}
Updated
$user=User::with(['projects','projects.versions'])->find(auth()->user()->id);
$result = $user->projects->map(function ($project) {
return $project->versions;
});
dd($result);
Use like below
$json = json_encode($responseOfController);
echo "<pre>";print_r($json);die;

JsonBackReference not working as expected

I have the next two clases...
Class A
#Entity
#Table(name="ClassA")
public class ClassA
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "Id", unique = true, nullable = false)
private Long id;
#Column(name = "Name", nullable = false, length = 50)
private String name;
#JsonManagedReference
#OneToMany(mappedBy="classA")
private List<ClassB> classBList;
}
Class B
#Entity
#Table(name = "ClassB")
public class ClassB
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "Id", unique = true, nullable = false)
private Long id;
#Column(name = "Name", nullable = false, length = 50)
private String name;
#JsonBackReference
#ManyToOne
#JoinColumn(name = "ClassAId", nullable = false)
private ClassA classA;
}
When i do a get of all ClassA records from database using REST the result is working like charm:
GET http://localhost:8080/REST/ClassA
[
{
"id": 1,
"name": "VVVV I",
"classB": [
{
"id": 1,
"name": "SSSS I"
},
{
"id": 2,
"name": "QQQQ II",
}
]
},
{
"id": 2,
"name": "RRRR II",
"classB": []
},
{
"id": 3,
"name": "FFFFF III",
"classB": []
},
{
"id": 4,
"name": "QWERR",
"classB": [
{
"id": 3,
"name": "GGGG III",
},
{
"id": 4,
"name": "HHHH IV",
},
{
"id": 5,
"name": "JJJJ V",
}
]
},
{
"id": 5,
"name": "TRRR",
"classB": []
}
]
The problem is when i want to get the list of ClassB, the ClassA is not returning at all...
GET http://localhost:8080/REST/ClassB
[
{
"id": 1,
"name": "SSSS I"
},
{
"id": 2,
"name": "QQQQ II"
},
{
"id": 3,
"name": "GGGG III"
},
{
"id": 4,
"name": "HHHH IV"
},
{
"id": 5,
"name": "JJJJ V"
}
]
I need ClassA (without classB inside of it) be listed when getting list of ClassB
How can i achieve that?
Best regards

Avoid circular self references in hibernate entity

I have a Hibernate entity with self references
#Entity
#Table(name = "category")
#NamedQuery(name = "Category.findAll", query = "SELECT c FROM Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, length = 255)
private String name;
#Column(length = 255)
private String description;
#Column(nullable = false, length = 25, columnDefinition = "enum('Category','SubCategory','Indicator')")
private String type;
#ManyToMany
#JoinTable(name = "CategoryHierarchy", joinColumns = #JoinColumn(name = "parentId", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "childId", referencedColumnName = "id"))
private List<Category> childs;
// getters and setters
}
So, obviously I was facing infinite recursion while deserializing the JSON when I was getting all the entities. So I added
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "#id")
above the class name.
But now, the JSON only contains ids or numbers like
{
"success": true,
"messages": [
{
"#id": 1,
"id": 5,
"name": "TestParentCategory ",
"description": "This is test Parent category",
"type": "Category",
"status": "New",
"childs": [
{
"#id": 2,
"id": 6,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:19",
"editedBy": null,
"createTime": "2016-03-23T11:40:19",
"createdBy": 10,
"type": "SubCategory",
"status": "New",
"childs": [
{
"#id": 3,
"id": 8,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:20",
"editedBy": null,
"createTime": "2016-03-23T11:40:20",
"createdBy": 10,
"type": "Indicator",
"status": "New",
"childs": [],
"parents": [
2,
{
"#id": 4,
"id": 7,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:19",
"editedBy": null,
"createTime": "2016-03-23T11:40:19",
"createdBy": 10,
"type": "SubCategory",
"status": "New",
"childs": [
3,
{
"#id": 5,
"id": 9,
"name": "TestChildCategory",
"description": "This is test child category",
"editTime": "2016-03-23T11:40:20",
"editedBy": null,
"createTime": "2016-03-23T11:40:20",
"createdBy": 10,
"type": "Indicator",
"status": "New",
"childs": [],
"parents": [
2,
4
],
"opinions": [],
"timestamp": "2016-03-23T11:40:20",
"edited": "2016-03-23T11:40:20"
}
]
}
],
},
]
}
]
},
2,
4,
3,
5
]
}
I dont want numbers in the array (2, 4, 3, 5) but I want actual objects. How can I do that?
UPDATE
I also went through the question
so is it the only way to do it?

json to java object with gson ( object nested with arraylist )

I want to create a object Checklist with the following JSON. But I think the Arraylist categories isn't created. I do not have an exception the debug console enter into bucle when create the object : " Background partial concurrent mark sweep GC freed 165848(5MB) AllocSpace objects, 144(1852KB) LOS objects, 22% free, 55MB/71MB, paused 5.343ms total 67.660ms "
{"type_check":"CAB","description":"simple cabin","categories":[{"category_id":"3","description":"Confort"},{"category_id":"4","description":"Servicios"},{"category_id":"5","description":"AlimentaciĆ³n"},{"category_id":"6","description":"Personal"},{"category_id":"7","description":"Instalaciones"}]}
And the following classes:
Checklist.class
public class Checklist {
private String type_check;
private String description;
private ArrayList<Category> categories;}
Category.class
public class Category {
private int category_id;
private String description;
}
Creating the object:
Gson gson = new GsonBuilder().create();
Checklist check = gson.fromJson(checklist.toString(), Checklist.class);
I must specify the arraylist when I parse the json?? Thanks and have a nice day.
this is how the json would look like with following code
[
{
"type_check": "CAB_0",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_1",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_2",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_3",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_4",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_5",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
},
{
"type_check": "CAB_6",
"description": "simple cabin",
"categories": [
{
"category_id": 0,
"description": "Description_0"
},
{
"category_id": 1,
"description": "Description_1"
},
{
"category_id": 2,
"description": "Description_2"
},
{
"category_id": 3,
"description": "Description_3"
},
{
"category_id": 4,
"description": "Description_4"
},
{
"category_id": 5,
"description": "Description_5"
},
{
"category_id": 6,
"description": "Description_6"
}
]
}
]
Checklist.Java code is here
public class Checklist {
private String type_check;
private String description;
private ArrayList<Category> categories;
public String getType_check() {
return type_check;
}
public void setType_check(String type_check) {
this.type_check = type_check;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ArrayList<Category> getCategories() {
return categories;
}
public void setCategories(ArrayList<Category> categories) {
this.categories = categories;
}
}
Category.java code is here
public class Category {
private int category_id;
private String description;
public int getCategory_id() {
return category_id;
}
public void setCategory_id(int category_id) {
this.category_id = category_id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
TestCode.Java code is here
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class TestCode {
public static void main(String[] args) {
ArrayList<Checklist> list = new ArrayList<Checklist>();
list = createList();
String stringJson = (new Gson()).toJson(list);
System.out.println("##### JSON from a object #######");
System.out.println(stringJson);
System.out.println("###### Convert JSON to object ######");
ArrayList<Checklist> list2 = new ArrayList<Checklist>();
list2 = (new Gson()).fromJson(stringJson,
new TypeToken<ArrayList<Checklist>>() {
}.getType());
System.out.println("####### print out put ######");
for (int i = 0; i < list2.size(); i++) {
Checklist checklist = list2.get(i);
System.out.println(checklist.getType_check() + "");
System.out.println(checklist.getDescription() + "");
ArrayList<Category> categorys = checklist.getCategories();
for (int j = 0; j < categorys.size(); j++) {
Category category = categorys.get(j);
System.out.println(category.getCategory_id() + "");
System.out.println(category.getDescription() + "");
}
}
}
private static ArrayList<Checklist> createList() {
// TODO Auto-generated method stub
ArrayList<Checklist> list = new ArrayList<Checklist>();
for (int i = 0; i < 7; i++) {
Checklist checklist = new Checklist();
checklist.setType_check("CAB_" + i);
checklist.setDescription("simple cabin");
ArrayList<Category> categorys = new ArrayList<Category>();
for (int j = 0; j < 7; j++) {
Category category = new Category();
category.setCategory_id(j);
category.setDescription("Description_" + j);
categorys.add(category);
}
checklist.setCategories(categorys);
list.add(checklist);
}
return list;
}
}