Можно ли делать выражения / вычисления в JSON?
Я использую замечательный json-сервер в качестве бэкэнда моего приложения, и он действительно полезен для создания пользовательских конечных точек для получения некоторых данных. но что было бы супер полезно, если бы это позволило мне делать вычисления / выражения, чтобы я мог имитировать это поведение бэкэнда тоже.
взять эту структуру данных, например
{
"products": [
{
"name": "football",
"id": "SPO-001",
"category": "sport",
"price": 40,
"couponApplied": "false",
"coupons": [
"daw124qdw",
"a1212cxn"
]
}
]
}
Я хотел бы как-то сказать "discountPrice": couponApplied ? price * couponDiscount
это только у меня псевдокодирование. но я хотел бы сделать кое-что, где я могу вычислить цену на лету. или когда я делаю запрос, он выполняет вычисление и возвращает мне вычисленные данные (как это делает бэкэнд-приложение)
Я понимаю, что могу сделать запрос, применить купон и предоставить эту новую цену. или даже сделать запрос на почту и изменить цену. но это все сделано на стороне клиента. Есть ли способ сделать это либо с помощью JSON или JSON-сервера или любых других решений. если это имеет смысл?
5 ответов
JSON означает JavaScript Object Notation
и является структурой данных, и не имеет никакого препроцессора для этого. Вы можете использовать любой анализатор JSON и динамически добавлять нужные значения.
Итак, вкратце: нет, нет возможности добавлять динамические значения
Нет, вы не сможете выполнять вычисления внутри json. Данные должны быть видоизменены в другом месте, а затем отправлены.
Нет, в 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;
Если вы пытаетесь создать логику динамически, например, пользователь создает некоторую логику, и вы хотите сохранить ее в БД, а затем применить где-нибудь, это может быть полезно:
- Анализатор формул в стиле Excel + немного JS-кодов для вставки данных в формулы.
- JSONLogic
- Операции конвейера агрегации MongoDB используются в массиве объектов. Такое же поведение можно использовать внутри объекта JSON, но вам нужна реализация, которая позаботится об этом, что-то вроде Mingo. Например, проверьте арифметическую сумму. Эта реализация 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
позволяют добавлять пользовательское промежуточное ПО. Таким образом, вы можете написать что-то вроде этого:
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)
})()
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);
При этом используется дескриптор метода доступа для определения свойства объекта, которое зависит от значений других свойств объекта.