7

I am using the wonderful json-server as the backend of my application and it's really useful for hitting custom endpoints to retrieve some data. but what would be super useful if it allowed me to do calculations/expression so that i can mimic that backend behaviour too.

take this data structure for example

{
  "products": [
    {
      "name": "football",
      "id": "SPO-001",
      "category": "sport",
      "price": 40,
      "couponApplied": "false",
      "coupons": [
        "daw124qdw",
        "a1212cxn"
      ]
    }
  ]
}

I would like some way of saying something like "discountPrice": couponApplied ? price * couponDiscount

that's just me pseudo coding. but I would like to do something where I can calculate the price on the fly. or when I make a request it does a calculation and returns me the calculated data (like a backend app would)

I understand I can make a request, apply the coupon and render that new price. or even make a post request and change the price. but that is all done client side. is there any way to do this either with json or json-server or any other solutions. if that makes sense?

Red Baron
  • 7,181
  • 10
  • 39
  • 86
  • `json-server` isn't super customizable, so might I suggest building a simple `express` server that will fit you needs. Then you can mock any backend functionality you want. – Galupuf Dec 20 '18 at 14:18
  • and then I have to build the backend myself? @Galupuf – Red Baron Dec 20 '18 at 14:20
  • Yes. It sounds to me like you need a more custom solution. Keep in mind building an `express` app to mock data is very simple. Take a look at this example: https://expressjs.com/en/starter/hello-world.html All you would need to do is add your custom data structure and you're golden. – Galupuf Dec 20 '18 at 14:22
  • No, for the same reason that we can not have this kind of thing in all equivalent languages: XML, YAML, csv ... They are designed to clarify data, not programs or even formulas – Mister Jojo Dec 20 '18 at 14:25
  • Note that json-server is built on express and [allows you to use custom middleware](https://github.com/typicode/json-server#add-middlewares), so you should be able to do the transform with a simple middleware function. – Scott Sauyet Dec 20 '18 at 14:31
  • Just to clarify, I am not saying that you have to build a custom backend, I'm just suggesting you should. In my experience, `json-server` is difficult to configure and I have found it much easier (and more configurable) to build a custom backend with `express` – Galupuf Dec 20 '18 at 14:35
  • @Galupuf yeh, I'm trying to move to express as you say, it seems more usable. how does the setup compare to json-server. I have my db.json file and that is just served up to me using json-server. how does similar look in express? – Red Baron Dec 20 '18 at 14:42
  • If your data is hardcoded, just use the code from the link I provided above and modify the response `res.send({products: [...]})`. Since it's just JS, you can perform operations and create variables as you mentioned in your question. There are a plethora of tutorials out there is you need an step by step example. – Galupuf Dec 20 '18 at 14:44
  • @Galupuf thanks. I have set something up and now hitting expected routes and getting stuff back. only thing im not sure on, how do you make a post request to express and then store the data and reuse that? for example when I update a products quantity, I was using an action creator to make a post request to json server so when i refreshed the page I got back the correctly updated quantity. at the moment im just using a javascript object inside my app.get(), how do I make this part dynamic json? – Red Baron Dec 20 '18 at 15:28
  • @Galupuf I'm slightly confused. you have done json.parse(data) on the data from the file reading from the db.json file. but where is the data that im making from the axios post request coming from? – Red Baron Dec 20 '18 at 19:29
  • @Galupuf figured it out finally :) – Red Baron Dec 20 '18 at 19:45

6 Answers6

10

JSON means JavaScript Object Notation and is data structure, and does not have any preprocessor for it. You can use any JSON parser and append/change values that you need dynamically.

So in short: no, there is no possibility to add dynamic values

Justinas
  • 41,402
  • 5
  • 66
  • 96
  • 1
    Yep. It's strictly notation and a way of formatting data. – Dadsquatch Dec 20 '18 at 14:17
  • 1
    is there any solutions to my problem? other people must have a want/need for this "mocking" of the backend that doesn't actually require building a backend? – Red Baron Dec 20 '18 at 14:17
4

No, you'll not be able to do computations inside json. The data would need to be mutated elsewhere and then sent.

Josh Kelly
  • 938
  • 5
  • 12
2

No, it isn't possible to do math or any kind of expression in JSON as JSON is just a data structure format, and not a programming language.

You will need to load the JSON data in using a programming language of your choice, at which point you can then manipulate it.

For example, since you mention javascript a simple Node program as an example..

//It would be better to use the FileSystem API, but for simplicity for this example, I'm using require
var json = require('./myjson.json'); 
var product = json.products[0];

//Since the dataset has "false", this if will handle both "false" (string) and false (boolean) values. The value should really be boolean if possible
product.discountPrice = product.couponApplied && product.couponApplied !== "false" ? product.price * couponDiscount : null;
Norman Breau
  • 2,132
  • 16
  • 35
2

If you are trying to create logic dynamically, like user creates some logic, and you want to save it into DB and later apply it somewhere, these might be useful:

In your example, using formula parser could be like:

const response = {
  "products": [
    {
      "name": "football",
      "id": "SPO-001",
      "category": "sport",
      "price": 40,
      "couponApplied": "false",
      "coupons": [
        "daw124qdw",
        "a1212cxn"
      ]
    },
    {
      "name": "football",
      "id": "SPO-001",
      "category": "sport",
      "price": 40,
      "couponApplied": "true",
      "couponDiscount": 0.2,
      "coupons": [
        "daw124qdw",
        "a1212cxn"
      ]
    }
  ],
  formulaFields: {
    "discountPrice": 'IF("{couponApplied}"="true", {price} * {couponDiscount}, "")', // excel standard formula, with {variable} as product field keys
  }
}

const productsWithValues = response.products.map((product)=>{
  const productWithValues = { ...product };
  for (const field in response.formulaFields){
    const formula = response.formulaFields[field].replace(/\{([^\}]+)\}/g, (_, key) => product[key])
    const parser = new Parser();
    const { result } = parser.parse(formula);
    productWithValues[field] = result;
  }
  return productWithValues;
})
console.log(productsWithValues)

Output:

[
  {
    "name": "football",
    "id": "SPO-001",
    "category": "sport",
    "price": 40,
    "couponApplied": "false",
    "coupons": ["daw124qdw", "a1212cxn"],
    "discountPrice": null
  },
  {
    "name": "football",
    "id": "SPO-001",
    "category": "sport",
    "price": 40,
    "couponApplied": "true",
    "couponDiscount": 0.2,
    "coupons": ["daw124qdw", "a1212cxn"],
    "discountPrice": 8
  }
]
Developia
  • 3,928
  • 1
  • 28
  • 43
0

JSON doesn't support this, but if you turn it into a Javascript object, you could do something like this:

var obj = JSON.parse(
`{
  "products": [
    {
      "name": "football",
      "id": "SPO-001",
      "category": "sport",
      "price": 40,
      "couponApplied": "true",
      "couponDiscount": 0.5,
      "coupons": [
        "daw124qdw",
        "a1212cxn"
      ]
    }
  ]
}`).products[0];

Object.defineProperty(obj,"discountPrice",{
  get:function(){
    return (this.couponApplied==="true"||this.couponApplied===true) ? this.price*this.couponDiscount : this.price;
  },
  set:function(){
    return;
  }
});

console.log(obj.discountPrice);

This uses an accessor descriptor to define an object property that depends on the values of the other object properties.

Feathercrown
  • 2,547
  • 1
  • 16
  • 30
0

Note that json-server allow you to add custom middleware. So you could write something like this:

const updateProduct = (p) => ({
  ...p,
  discountPrice: p.couponApplied ? p.price * p.couponDiscount : p.price
})

const transform = ({products, ...rest}) => ({
  ...rest, 
  products: products.map(updateProduct)
})

const modify = (req, res, next) => {
  if (req.path !== '/my-route') return next();

  res.body = JSON.stringify(transform(JSON.parse(res.body)))
  next();
}


// dummy call -- would really be handled by json-server/express

(() => {
  const req = {path: '/my-route'};
  const res = {body: `{"products":[{"name":"football","id":"SPO-001","category":"sport","price":40,"couponApplied":false,"coupons":["daw124qdw","a1212cxn"]},{"name":"helmet","id":"SPO-042","category":"sport","price":50,"couponApplied":true,"couponDiscount":0.75,"coupons":["foobarbaz"]}]}`}
  const next = () => {console.log(JSON.parse(res.body))}
  
  modify(req, res, next)
})()
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103