合并两个JSONata表达式

时间:2019-09-25 20:35:16

标签: javascript json transformation jsonata

我正在使用JSONata执行从JSON到JSON的转换。

出于某些独特的原因,我想合并两个JSONata表达式:

例如:

父母的表情:

var script = `
{
      "data":
      {
          "name" : data.payload.Name.(FirstName & ' ' & LastName),    
          "alias": data.payload.Name.(Salutation & ' ' & FirstName),
          "active": data.payload.Status = 'New' ? true : false,
          "signature": "Have good day ," & data.payload.Name.FirstName & "!"
       }       
  }
`;

我也有一些简单的JSONata表达式,例如:

表达式1:

{
   "source" : source
}

表达式2:

{
  "data": {
     "email" : data.payload.Email
   }
}

我想将上述两个表达式添加到使用script定义的表达式中。

所以在添加了这两个表达式之后,我应该可以得到:

var script = `
{
      "source": source,
      "data":
      {
          "name" : data.payload.Name.(FirstName & ' ' & LastName),    
          "alias": data.payload.Name.(Salutation & ' ' & FirstName),
          "active": data.payload.Status = 'New' ? true : false,
          "signature": "Have good day ," & data.payload.Name.FirstName & "!",
          "email": data.payload.Email
       }       
  }
`;

如何使用javascript / JSONata?

背景和限制:

  1. 子表达式(在示例中为表达式1和2)(应该添加到父表达式中)始终像"a" : x.y.z or "b" : x这样简单的赋值。

  2. 子表达式可能已经存在于父表达式中。在这种情况下,它将替换分配。

  3. 我也想从父表达式(如果存在的话,如果存在的话)中删除一些json路径,例如If delete path data.Email

我做了什么? :

  • 我试图通过将值放在双引号下并使用escape()函数对值进行编码来将JSONata脚本转换为JSON。
  • 一旦有了JSON,我就会寻找子表达式(例如data.Email)中提到的路径

    • 如果路径存在:替换其值
    • 如果路径不存在:创建路径并分配值
    • 如果应该删除路径:只需将其删除。
  • 完成JSON以上的处理后, 通过使用一串正则表达式删除引号,然后将unescape()方法用于解码,将其转换为JSONata脚本。

  • 此方法的问题是:

    • 不可靠(正则表达式匹配和替换不是完全可靠的)
    • 我不确定是否可以始终将每个JSONata(不声明任何函数)都转换为有效的JSON。

2 个答案:

答案 0 :(得分:1)

我认为您最好的选择是将表达式转换为JSONata AST,然后将它们合并为新的AST。

这是一个非常简单的示例:

const ast1 = jsonata(expr1).ast();
const ast2 = jsonata(expr1).ast();

if (ast1.type !== "unary" || ast2.type!== "unary") throw Error("Only support unary expressions")

const combinedAst = {
  "type": "unary",
  "value": "{",
  "lhs": [...ast1.lhs, ast2.lhs]   
 }

 // TODO: Serialize the AST or inject it into jsonata() 

问题在于如何处理新的AST。就我而言,我还编写了一个自定义序列化程序,将AST转换回JSONata字符串,并对其进行评估。


正在使用的AST

表达式1的AST

{
  "type": "unary",
  "value": "{",
  "position": 1,
  "lhs": [
    [
      {
        "value": "source",
        "type": "string",
        "position": 13
      },
      {
        "type": "path",
        "steps": [
          {
            "value": "source",
            "type": "name",
            "position": 22
          }
        ]
      }
    ]
  ]
}

表达式2的AST

{
  "type": "unary",
  "value": "{",
  "position": 1,
  "lhs": [
    [
      {
        "value": "data",
        "type": "string",
        "position": 10
      },
      {
        "type": "unary",
        "value": "{",
        "position": 13,
        "lhs": [
          [
            {
              "value": "email",
              "type": "string",
              "position": 26
            },
            {
              "type": "path",
              "steps": [
                {
                  "value": "data",
                  "type": "name",
                  "position": 33
                },
                {
                  "value": "payload",
                  "type": "name",
                  "position": 41
                },
                {
                  "value": "Email",
                  "type": "name",
                  "position": 47
                }
              ]
            }
          ]
        ]
      }
    ]
  ]
}

组合式AST

{
  "type": "unary",
  "value": "{",
  "position": 1,
  "lhs": [
    [
      {
        "value": "source",
        "type": "string",
        "position": 12
      },
      {
        "type": "path",
        "steps": [
          {
            "value": "source",
            "type": "name",
            "position": 20
          }
        ]
      }
    ],
    [
      {
        "value": "data",
        "type": "string",
        "position": 30
      },
      {
        "type": "unary",
        "value": "{",
        "position": 33,
        "lhs": [
          [
            {
              "value": "email",
              "type": "string",
              "position": 46
            },
            {
              "type": "path",
              "steps": [
                {
                  "value": "data",
                  "type": "name",
                  "position": 53
                },
                {
                  "value": "payload",
                  "type": "name",
                  "position": 61
                },
                {
                  "value": "Email",
                  "type": "name",
                  "position": 67
                }
              ]
            }
          ]
        ]
      }
    ]
  ]
}

答案 1 :(得分:0)

最近我做了类似的事情。想法是像这样使用$merge

$merge([$, {"modality": "watch"}])

Github

Demo link