如何将 hylang s-expression 序列化为 PostgreSQL json/json-b?
How to serialize hylang s-expression into PostgreSQL json/json-b?
我们正在尝试使用hylang作为一些金融业务流程的DSL。我们试图将业务规则用作 JSON,但使用 hy 语言切换到 DSL。现在我们需要像以前的 JSON-B 项一样将 s-expression 项持久化到 postgreSQL 中。有没有标准的方法可以做到这一点,或者我们必须改用文本字段?
上一个:
"conditions": {
"all": [
{
"name": "order_create_date",
"value": 1620675000,
"operator": "greater_than_or_equal_to"
},
{
"name": "order_create_date",
"value": 1624217400,
"operator": "less_than_or_equal_to"
}
}
当前:
(defn check_condition [params] (
and (> params.order_create_date "2021/06/22") (< params.order_create_date "2021/07/22"))
)
确实没有标准的方法来做到这一点;在 Hy 或 Postgres 方面没有实现任何特别的东西。除非你真的有大量的这些,或者它们非常大,或者你想对它们进行某种奇特的搜索或索引,否则将它们存储为文本应该没问题。事实上,我更喜欢平面文件而不是数据库。
另一种选择是利用 Postgres 的 JSON 支持并设计您自己的在 Hy 模型树和 JSON 之间转换的小方法。例如,Hy 表达式可以表示为 JSON 数组。 Python 的 json
库可以帮助解决这个问题,例如JSONEncoder
的 default
参数。
有2种解决方案:
使用像 'sexpdata' 这样的库来解析和反解析 S 表达式 to/from Python 列表,然后使用 JSON 加上一些自定义 enc/dec.
使用 pyparsing 将 S-Expression 解析为 Python 列表,然后使用 json.
import pyparsing as pp
import json
LP = pp.Literal("(").suppress()
RP = pp.Literal(")").suppress()
String = pp.Word(pp.alphanums + '_,.#@<>=+=/*%[]')
SingleQuoteString = pp.QuotedString(quoteChar="'", unquoteResults=False)
DoubleQuoteString = pp.QuotedString(quoteChar='"', unquoteResults=False)
QuotedString = SingleQuoteString | DoubleQuoteString
Atom = String | QuotedString
SExpr = pp.Forward()
SExprList = pp.Group(pp.ZeroOrMore(SExpr | Atom))
SExpr << (LP + SExprList + RP)
def to_json(expr: str) -> str:
return json.dumps(SExpr.parseString(expr).asList())
def from_json(val: str) -> str:
if isinstance(val, list):
return f"({' '.join(from_json(e) for e in val)})"
else:
return str(val)
我们正在尝试使用hylang作为一些金融业务流程的DSL。我们试图将业务规则用作 JSON,但使用 hy 语言切换到 DSL。现在我们需要像以前的 JSON-B 项一样将 s-expression 项持久化到 postgreSQL 中。有没有标准的方法可以做到这一点,或者我们必须改用文本字段?
上一个:
"conditions": {
"all": [
{
"name": "order_create_date",
"value": 1620675000,
"operator": "greater_than_or_equal_to"
},
{
"name": "order_create_date",
"value": 1624217400,
"operator": "less_than_or_equal_to"
}
}
当前:
(defn check_condition [params] (
and (> params.order_create_date "2021/06/22") (< params.order_create_date "2021/07/22"))
)
确实没有标准的方法来做到这一点;在 Hy 或 Postgres 方面没有实现任何特别的东西。除非你真的有大量的这些,或者它们非常大,或者你想对它们进行某种奇特的搜索或索引,否则将它们存储为文本应该没问题。事实上,我更喜欢平面文件而不是数据库。
另一种选择是利用 Postgres 的 JSON 支持并设计您自己的在 Hy 模型树和 JSON 之间转换的小方法。例如,Hy 表达式可以表示为 JSON 数组。 Python 的 json
库可以帮助解决这个问题,例如JSONEncoder
的 default
参数。
有2种解决方案:
使用像 'sexpdata' 这样的库来解析和反解析 S 表达式 to/from Python 列表,然后使用 JSON 加上一些自定义 enc/dec.
使用 pyparsing 将 S-Expression 解析为 Python 列表,然后使用 json.
import pyparsing as pp import json LP = pp.Literal("(").suppress() RP = pp.Literal(")").suppress() String = pp.Word(pp.alphanums + '_,.#@<>=+=/*%[]') SingleQuoteString = pp.QuotedString(quoteChar="'", unquoteResults=False) DoubleQuoteString = pp.QuotedString(quoteChar='"', unquoteResults=False) QuotedString = SingleQuoteString | DoubleQuoteString Atom = String | QuotedString SExpr = pp.Forward() SExprList = pp.Group(pp.ZeroOrMore(SExpr | Atom)) SExpr << (LP + SExprList + RP) def to_json(expr: str) -> str: return json.dumps(SExpr.parseString(expr).asList()) def from_json(val: str) -> str: if isinstance(val, list): return f"({' '.join(from_json(e) for e in val)})" else: return str(val)