是否可以在 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)
})()
如果您正在尝试动态创建逻辑,例如用户创建一些逻辑,并且您想将其保存到数据库中并稍后将其应用到某个地方,这些可能会有用:
- 像formula parser这样的Excel + 一些用于将数据放入公式的JS代码。
- JSONLogic
- MongoDB aggregation pipeline operations are being used in an Array of Object. Same behavior can be used inside JSON object, but you need an implementation to take care of it, something like Mingo. Check arithmetic sum 例如。这个 JS 实现可能会有所帮助。
在您的示例中,使用公式解析器可能类似于:
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
}
]
我正在使用出色的 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)
})()
如果您正在尝试动态创建逻辑,例如用户创建一些逻辑,并且您想将其保存到数据库中并稍后将其应用到某个地方,这些可能会有用:
- 像formula parser这样的Excel + 一些用于将数据放入公式的JS代码。
- JSONLogic
- MongoDB aggregation pipeline operations are being used in an Array of Object. Same behavior can be used inside JSON object, but you need an implementation to take care of it, something like Mingo. Check arithmetic sum 例如。这个 JS 实现可能会有所帮助。
在您的示例中,使用公式解析器可能类似于:
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
}
]