1

Assuming I have a tree structure, like

Categories:

  Category1
    Subcategory11
    Subcategory12
  Category2
    Subcategory21
    Subcategory22
  ...

Category and Subcategory are the same data type (Category). Potentially there could be > 2 levels of enclosure.

What would be the best way to represent the query that returns all top categories? Is something like www.mysite.com/api/categories or www.mysite.com/api/categories/top work?

Assuming I'd like to return the whole list of categories in one REST call, what would that endpoint be and would such a requirement violate REST principles? Can I use something like www.mysite.com/api/categories/tree?

BTW, I did see the How should a REST URL schema look like for a tree hierarchy?, but that is not a pure example of tree of homogeneous nodes.

Community
  • 1
  • 1
Nestor Milyaev
  • 5,845
  • 2
  • 35
  • 51
  • 1
    First and formost, REST has hardly anything to do with URI design; RESTs intention are the decoupling of API/server and their clients. HTTP offers content-type negotiation which a client can use to tell the server what representation the response should look like. You could therefore define a media-type which only includes the top-categories (i.e. `application/vnd.yourComp.category.top+json`) and one which contains the full hierarchy (i.e. `application/vnd.yourComp.category.full+xml`) and then let the client decide what it want to see. – Roman Vottner Jan 11 '17 at 16:42
  • I thinks you need DFS Algorithm and this implementation examples. https://www.cis.upenn.edu/~matuszek/cit594-2003/Examples/TreeTraversals/TreeTraversals.java – Musa Nov 07 '17 at 18:47

1 Answers1

1

I thinks you need DFS Algorithm and this implementation examples.... (https://www.cis.upenn.edu/~matuszek/cit594-2003/Examples/TreeTraversals/TreeTraversals.java)

But You can pass this method all Category and get tree of this Category. And additionally I want to mention that, you can use CategoryDTO and relative CategoryMapper to represent better style on response (on representation layer e.g. - restful)

// for readability setters, getters and others fields (and code parts) are omitted

public class Category implements Serializable, Comparable<Category> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "created_on")
    private Instant createdOn;

    @Column(name = "created_by")
    private String createdBy;

    @Column(name = "status")
    private Integer status;

    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    private Category parent;

    @Transient
    private List<Category> child = new ArrayList<>();

    }

this is method which returns list of Category tree

private List<Category> createTreeCategoriesByParent(final List<Category> categories, Long parentId) {
        List<Category> siblings;
            siblings = new ArrayList<>();
            categories.forEach(category -> {
                if (Objects.equals(category.getParent() == null ? null : category.getParent().getId(), parentId)) {
                    List<Category> children = createTreeCategoriesByParent(categories, category.getId());
                    children.sort(Category::compareTo);
                    category.setChild(children);
                    siblings.add(category);
                }
            });
            return siblings;
    }

Your input Category will

[
  {
    "status": 1,
    "name": "Woman",
    "accOrder": 0,
    "parentId": null,
    "child": []
  },
  {
    "status": 1,
    "name": "Man",
    "accOrder": 0,
    "parentId": null,
    "child": []
  },
  {
    "status": 1,
    "name": "Shoes",
    "accOrder": 0,
    "parentId": 1,
    "child": []
  },
  {
    "status": 1,
    "name": "Bijoux",
    "accOrder": 1,
    "parentId": 1,
    "child": []
  },
  {
    "status": 1,
    "name": "Sneckers",
    "accOrder": 1,
    "parentId": 3,
    "child": []
  },
  {
    "status": 0,
    "name": "Kids",
    "accOrder": 1,
    "parentId": null,
    "child": []
  },
  {
    "status": 1,
    "name": "Good Sneckers",
    "accOrder": 1,
    "parentId": 5,
    "child": []
  },
  {
    "status": 1,
    "name": "Bad Snackers",
    "accOrder": 2,
    "parentId": 5,
    "child": []
  }]

Output is

[
  {
    "status": null,
    "name": "Woman",
    "accOrder": 0,
    "parentId": null,
    "child": [
      {
        "status": null,
        "name": "Shoes",
        "accOrder": 0,
        "parentId": 1,
        "child": [
          {
            "status": null,
            "name": "Sneckers",
            "accOrder": 1,
            "parentId": 3,
            "child": [
              {
                "createdBy": null,
                "status": null,
                "name": "Good Sneckers",
                "accOrder": 1,
                "parentId": 5,
                "child": []
              },
              {
                "status": null,
                "name": "Bad Snackers",
                "accOrder": 2,
                "parentId": 5,
                "child": []
              }
            ]
          }
        ]
      },
      {
        "status": null,
        "name": "Bijoux",
        "accOrder": 1,
        "parentId": 1,
        "child": []
      }
    ]
  },
  {
    "status": null,
    "name": "Man",
    "accOrder": 0,
    "parentId": null,
    "child": [
      {
        "status": null,
        "name": "T-shirt",
        "accOrder": 1,
        "parentId": 2,
        "child": []
      }
    ]
  },
  {
    "status": null,
    "name": "Kids",
    "accOrder": 1,
    "parentId": null,
    "child": []
  },
  {
    "status": null,
    "name": "Furniture",
    "accOrder": 4,
    "parentId": null,
    "child": []
  }
]
Musa
  • 2,596
  • 26
  • 25