2016-11-19 11 views
1

JavaScriptで複雑なオブジェクトを検証する必要があります。私はAJVバリデータと検証スキーマを作るスパース行列データオブジェクトを検証するためにJSONスキーマが必要です

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

:ペアの

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

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

オブジェクトが辞書に基づいています。

スキーマの要件:

  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秒かかる(バリデーションは速く、コンパイルは遅い)。さらに、それはメモリ例外の時間を捨てる。より良い検証スキーマを作ることは可能ですか?

答えて

2

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

v5/6 proposalsに追加したプロパティ名のキーワードは、ajv-keywordsパッケージで利用できます。

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); 

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

あなたは(ES6プロパティ構文を使用して)現在の標準バージョンに存在する同じ使用patternPropertiesキーワードを達成することができます

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

propertyNamesが簡単になりますし、より速く、私は考えるべきです。 items結果の上にマッピングすることで

+0

非常に興味深いです。あなたは 'propertyNames'の仕様を参照していますか?たとえ「enum」さえも例の上にありますが、[specification](http://json-schema.org/latest/json-schema-validation.html)にはありません。 – Hurelu

+0

最初の方法はいいですが、ブラウザにajv-keywordsを追加する方法はありません。出来ますか? 2番目の方法も良いですが、実際に辞書にはシンボルを持つことができる人の名前が含まれています。だから、正規表現を作ることは可能ですが、不幸にもarr.join( '|')だけではありません。 また、 "@ref"構文を使用しようとしましたが、コンパイル時間は変わりません。それはAjvが同じ@refサブスキーマを何度もコンパイルすることを意味しますか? – NtsDK

+0

@Hurelu propertyNamesはプロポーザルです(リンクを参照)。これはajvのカスタムキーワードとして使用できます。enumは仕様です - http://json-schema.org/latest/json-schema-validation.html#rfc。 section.5.20 – esp

1

はありませんが、1Nスキーマ(あなたが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>

+0

この方法も良いですが、実際に辞書にはシンボルを持つことができる人の名前が含まれています。だからmonsterRegexを作ることは可能ですが、不幸にもarr.join( '|')だけではありません。すべてのregexスペシャルをオートエスケープすることは可能ですか? – NtsDK

+1

この場合、JSONスキーマを使用せずにオブジェクトを直接検証する方が簡単でしょう。 – Hurelu

関連する問題