Search code examples
javascriptnode.jsjsonjson-server

Relation in Json-server


I want to create a database using "json-server" and I also used the "relation" topic, but I can't get the products of the user's shopping cart? Where is the problem? Thank you for helping me.

My "db.json" file example is as follows:

{
  "products": [
    { "id": 1, "title": "json-server", "author": "typicode" },
    { "id": 2, "title": "json-server", "author": "typicode" }
  ],
  "users": [
    {
      "id": 1,
      "name": "user-1",
      "cart": [
        { "id": 1, "productId": 1 },
        { "id": 2, "productId": 2 }
      ]
    }
  ]
}

And my example "URL" is as follows: http://localhost:5000/users?_expand=product

i wanna to tried get products in user's cart, and i couldn't get it!


Solution

  • "json-server": "^0.17.0"

    The _expand and _embed will look up the foreign key on the top-level JSON object, not the nested object.

    When you try to access /users?_expand=product resource, json-server will use expand() function to handle the ?_expand=product URL parameter.

    function expand(resource, e) {
      e &&
        [].concat(e).forEach((innerResource) => {
          const plural = pluralize(innerResource)
          if (db.get(plural).value()) {
            const prop = `${innerResource}${opts.foreignKeySuffix}`
            resource[innerResource] = db
              .get(plural)
              .getById(resource[prop])
              .value()
          }
        })
    }
    

    resource is:

    {
      id: 1,
      name: "user-1",
      cart: [
        {
          id: 1,
          productId: 1,
        },
        {
          id: 2,
          productId: 2,
        },
      ],
    }
    

    e is 'product', plural is 'products', prop is productId

    First, it will check if there are products data in the database using db.get(plural).value().

    The resource[innerResource] = db.get(plural).getById(resource[prop]).value() statement is the key. It will try to populate the product field with the product data get from the database by productId(get the value from the resource object). When it executes, it will be:

    resource['product'] = db.get('products').getById(resource['productId']).value()
    

    As you can see, there is no 'productId' field on the resource object. That's why json-server can't expand or embed data for nested objects.

    So, we have to adjust the data structure in the database to below:

    db.json:

    {
        "products": [
            { "id": 1, "title": "json-server", "author": "typicode" },
            { "id": 2, "title": "json-server", "author": "typicode" }
        ],
        "users": [
            { "id": 1, "name": "user-1" },
            { "id": 2, "name": "user-2" }
        ],
        "cart": [
            { "id": 1, "productId": 1, "userId": 1 },
            { "id": 2, "productId": 2, "userId": 1 },
            { "id": 3, "productId": 1, "userId": 2 }
        ]
    }
    

    Start the JSON server:

    npx json-server db.json
    
      \{^_^}/ hi!
    
      Loading db.json
      Done
    
      Resources
      http://localhost:3000/products
      http://localhost:3000/users
      http://localhost:3000/cart
    
      Home
      http://localhost:3000
    

    http://localhost:3000/user/1/cart?_expand=product&_expand=user:

    [
        {
            "id": 1,
            "productId": 1,
            "userId": 1,
            "product": {
                "id": 1,
                "title": "json-server",
                "author": "typicode"
            },
            "user": {
                "id": 1,
                "name": "user-1"
            }
        },
        {
            "id": 2,
            "productId": 2,
            "userId": 1,
            "product": {
                "id": 2,
                "title": "json-server",
                "author": "typicode"
            },
            "user": {
                "id": 1,
                "name": "user-1"
            }
        }
    ]
    

    http://localhost:3000/user/2/cart?_expand=product&_expand=user:

    [
        {
            "id": 3,
            "productId": 1,
            "userId": 2,
            "product": {
                "id": 1,
                "title": "json-server",
                "author": "typicode"
            },
            "user": {
                "id": 2,
                "name": "user-2"
            }
        }
    ]
    

    http://localhost:3000/users/?_embed=cart:

    [
        {
            "id": 1,
            "name": "user-1",
            "cart": [
                {
                    "id": 1,
                    "productId": 1,
                    "userId": 1
                },
                {
                    "id": 2,
                    "productId": 2,
                    "userId": 1
                }
            ]
        },
        {
            "id": 2,
            "name": "user-2",
            "cart": [
                {
                    "id": 3,
                    "productId": 1,
                    "userId": 2
                }
            ]
        }
    ]