2

JavaScript で複雑なオブジェクトを検証する必要があります。

オブジェクトは辞書に基づいています:

var dict = {'1':true,'2':true,'3':true};

ペアのオブジェクト ストア マトリックス (通常は完全ではない):

var obj = {'1':{
        '1': 'str1',
        '2': 'str2',
        '3': 'str3',
    },'2':{
        '1': 'str1',
        '2': 'str2',
    }
};

AJVバリデーターでバリデーションスキーマを作っています。

スキーマ要件:

  1. 第 1 レベルのオブジェクトには、ディクショナリのプロパティのみが含まれます。
  2. 第 2 レベルのオブジェクトには、ディクショナリのプロパティのみが含まれます。
  3. データは文字列です

スキーマの生成:

var dict = {'1':true,'2':true,'3':true};

var subProperties = R.map(function(item){
  return {
    'type' : 'string',
    "minLength": 1,
  }
}, dict);
var root = {
  "type" : "object",
  "additionalProperties" : false
};
root.properties = R.map(function(item){
  return {
    "type" : "object",
    'properties' : subProperties,
    "additionalProperties" : false
  };
}, dict);

console.log(root)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.9.0/ajv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>

このスキーマはうまく機能していますが、問題はパフォーマンスです。ディクショナリに 200 個の要素が含まれている場合、このスキーマをコンパイルするには 10 秒かかります (検証は高速ですが、コンパイルは低速です)。さらに、メモリ不足の例外が時々スローされます。より良い検証スキーマを作成することは可能ですか?

4

2 に答える 2

3

40000 個のプロパティを検証していることを考えると、メモリ例外は驚くべきことではありません。検証関数のコード サイズは約 30Mb にする必要があります。

私がv5/6 プロポーザルに追加したajv-keywordsパッケージで利用可能なpropertyNames キーワードを使用できます。

var dict = ['1', '2', '3'];
var schema = {
  type: 'object',
  propertyNames: { enum: dict },
  additionalProperties: {
    type: 'object',
    propertyNames: { enum: dict },
    additionalProperties: {
      type: 'string',
      minLength: 1
    }
  }
};

var ajv = require('ajv')();
require('ajv-keywords')(ajv, 'propertyNames');

var validate = ajv.compile(schema);

このスキーマは小さいですが、同じことを行います。

現在の標準バージョンに存在する patternProperties キーワードを使用して同じことを実現できます (es6 プロパティ構文を使用):

var names = '^(1|2|3)$';
var schema = {
  type: 'object',
  additionalProperties: false,
  patternProperties: {
    [names]: {
      type: 'object',
      additionalProperties: false,
      patternProperties: {
        [names]: {
          type: 'string',
          minLength: 1
        }
      }
    }
  }
};

propertyNames はよりシンプルに見え、より高速になるはずです。

于 2016-11-19T10:50:26.693 に答える
1

結果をマッピングすることはスキーマitemsではありません1(Nつまり、200 個のアイテムがある場合、キーを検証するためだけに 200 個のスキーマが作成されます)。

patternProperties別の方法としては、200 の巨大なキーを使用するかRegExp、より単純に、オブジェクトを手動で検証するだけです。

var dict = {'1':true,'2':true,'3':true};

var monsterRegex = '^' + Object.keys(dict).join('|') + '$'

var valSchema = {
  type: 'string',
  minLength: 1
}
var keySchema = {
  type: 'object',
  additionalProperties: false,
  patternProperties: {}
}
keySchema.patternProperties[monsterRegex] = valSchema

var objSchema = {
  type: 'object',
  additionalProperties: false,
  patternProperties: {}
}
objSchema.patternProperties[monsterRegex] = keySchema

console.log(objSchema)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.9.0/ajv.min.js"></script>

于 2016-11-19T11:07:44.517 に答える