语言不可知规则规范

时间:2018-02-28 00:18:32

标签: configuration cross-platform rules

我当前项目的一个要求是能够根据特定条件为客户选择目标URL,并且这些条件可能具有AND / OR运算符并且也具有嵌套条件。一个简单的熟练例子:

if (device == 'android' || device == 'iOS') {
    if ( (flag1 == 'x' && productId == 'ABC123') || (flag1 == 'y' && productId == 'EFG345') ) {
      return url1;
    }
}
else if (device == 'mac' || device == 'windows') {
   ...
}

如果您正在构建此服务,那么非常简单,但我们的挑战是需要将这个逻辑提供给我们的供应商,他们负责为客户群的特定部分选择URL,并且他们都使用不同的实现语言 - Java,Go-Lang,Python,你的名字。

问题是,假设已经填充了诸如device,flag1,productId等变量,是否有一种语言无关的方式来指定这些规则,例如在JSON中?

我看了看:Representing logic as data in JSON

我喜欢使用类似的建议:

["AND",
    {"var1" : "value1"},
    ["OR",
        { "var2" : "value2" },
        { "var3" : "value3" }
    ]
]

但我没有看到任何可以读取此JSON的标准解析器,并以所选择的特定语言应用规则。是否有任何标准解决方案可以帮助满足此要求,而无需多个自定义解析器和容易出错的实现?

PS:我们可以让每个供应商为这个选择逻辑编写自己的代码片段,但挑战是规则可能会经常更改,我们不想等待几家不同的公司推出代码每次我们更改规则时都会更改其系统。我们还考虑过编写服务并让供应商给我们打电话,以便集中访问这些规则,但这意味着额外的网络调用(或者维护缓存并继续轮询我们的服务)。此外,并非所有供应商都愿意在选择URL时调用服务。

1 个答案:

答案 0 :(得分:0)

我已经创建了一个JSON模式来描述你的逻辑类型:

{
  "id": "http://json-schema.org/geo",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "description": "A languge-independent logic representation",
  "$ref": "#/definitions/Term",
  "definitions": {
    "Term": {
      "type": "object",
      "additionalProperties": false,
      "description": "A logical value",
      "properties": {
        "kind": { "$ref": "#/definitions/Kind" },
        "x": { "$ref": "#/definitions/Term" },
        "y": { "$ref": "#/definitions/Term" },
        "value": { "$ref": "#/definitions/Value" }
      },
      "required": ["kind"],
      "title": "Term"
    },
    "Value": {
      "type": "object",
      "additionalProperties": false,
      "description": "A key-value term",
      "properties": {
        "key": { "type": "string" },
        "value": { "type": "string" }
      },
      "required": [ "key", "value"],
      "title": "Term"
    },
    "Kind": {
      "description": "The kind of term",
      "type": "string",
      "enum": ["and", "or", "not", "value"],
      "title": "Kind"
    }
  }
}

以下是符合模式的数据示例(请注意,我的结构比您的示例略有规律):

{
  "kind": "and",
  "x": {
    "kind": "value",
    "value": { "key": "var1", "value": "value1" }
  },
  "y": {
    "kind": "or",
    "x": {
      "kind": "value",
      "value": { "key": "var2", "value": "value2" }
    },
    "y": {
      "kind": "value",
      "value": { "key": "var3", "value": "value3" }
    }
  }
}

(我认为你可以使用模式来获得更简洁和/或更安全的东西)。

我已经使用quicktype在C ++,Go,Swift,Objective-C,Java,C#,JavaScript等中生成类型和JSON封送处理代码。例如,以下是Swift表示和解析说明:

// To parse the JSON, add this file to your project and do:
//
//   let term = try? JSONDecoder().decode(Term.self, from: jsonData)

import Foundation

/// A logical value
class Term: Codable {
    let kind: Kind
    let x, y: Term?
    let value: TermValue?
}

/// The kind of term
enum Kind: String, Codable {
    case and = "and"
    case not = "not"
    case or = "or"
    case value = "value"
}

/// A key-value term
struct TermValue: Codable {
    let key, value: String
}

这是Go实施:

// To parse and unparse this JSON data, add this code to your project and do:
//
//    term, err := UnmarshalTerm(bytes)
//    bytes, err = term.Marshal()

package main

import "encoding/json"

func UnmarshalTerm(data []byte) (Term, error) {
    var r Term
    err := json.Unmarshal(data, &r)
    return r, err
}

func (r *Term) Marshal() ([]byte, error) {
    return json.Marshal(r)
}

// A logical value
type Term struct {
    Kind  Kind       `json:"kind"` 
    X     *Term      `json:"x"`    
    Y     *Term      `json:"y"`    
    Value *TermValue `json:"value"`
}

// A key-value term
type TermValue struct {
    Key   string `json:"key"`  
    Value string `json:"value"`
}

// The kind of term
type Kind string
const (
    And Kind = "and"
    Not Kind = "not"
    Or Kind = "or"
    Value Kind = "value"
)

转到https://app.quicktype.io/?gist=2c9dce4022d3e4987a6e8b48752850cc以使用架构并生成各种语言的代码。但是,您仍然需要在每种语言中定义评估函数。