是否可以在 json 中执行 expressions/calculations?

Is it possible to do expressions/calculations in json?

我正在使用出色的 json-server 作为我的应用程序的后端,它对于点击自定义端点以检索一些数据非常有用。但是如果它允许我做 calculations/expression 这样我也可以模仿后端行为,那将是非常有用的。

以这个数据结构为例

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

我想要某种表达方式,例如 "discountPrice": couponApplied ? price * couponDiscount

这只是我的伪编码。但我想做一些可以即时计算价格的事情。或者当我发出请求时,它会进行计算,然后 returns 我计算出的数据(就像后端应用程序那样)

我知道我可以提出请求、应用优惠券并提供新价格。甚至提出 post 请求并更改价格。但这都是在客户端完成的。有没有办法用 json 或 json-server 或任何其他解决方案来做到这一点。这是否有意义?

不,您将无法在 json 中进行计算。数据需要在别处进行变异然后发送。

JSON 表示 JavaScript Object Notation 并且是数据结构,并且没有任何预处理器。您可以使用动态需要的任何 JSON 解析器和 append/change 值。

简而言之:不,不可能添加动态值

不,不可能在 JSON 中进行数学运算或任何类型的表达式,因为 JSON 只是一种数据结构格式,而不是一种编程语言。

您将需要使用您选择的编程语言加载 JSON 数据,然后您可以对其进行操作。

例如,既然你提到 javascript 一个简单的 Node 程序作为例子..

//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;

JSON 不支持这个,但是如果你把它变成一个 Javascript 对象,你可以这样做:

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);

这使用访问器描述符来定义一个对象 属性,该对象依赖于其他对象属性的值。

请注意 json-server 允许您 add custom middleware。所以你可以这样写:

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)
})()

如果您正在尝试动态创建逻辑,例如用户创建一些逻辑,并且您想将其保存到数据库中并稍后将其应用到某个地方,这些可能会有用:

在您的示例中,使用公式解析器可能类似于:

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)

输出:

[
  {
    "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
  }
]