Hiqus-ヒエラリカルクエリストリング

これは、ツリーに似たデータ構造を人間に優しい形式で1行として表すための形式です。 これは、「application / x-www-form-urlencoded」形式の一般化であり、その結果、下位互換性があります。 Hiqusは、キーと値のペアの形式でデータを表示するという同じ原則に基づいていますが、唯一の違いは、キーを複合または空にすることができることです。



この形式は、Yandex(http://yandex.ru/yandsearch?date=within&text=hiqus&from_day=28&from_month=4&from_year=2009)、Google(http://www.google.ru/search?as_q=hiqus&hl= ru&num = 10&as_qdr = all)と、クエリ文字列で階層データを渡す必要がある他の多くのユーザー。 例外は、独自の形式が伝統的に使用されているPHPサイトです。これはあまり明確ではありません(たとえば、私はそれをすぐに見つけられませんでしたが、次のようになります。?User%5Bid%5D = 123&user%5Bname%5D = Nick)。



説明

hiqus文字列は、通常のクエリ文字列でよく知られているアンパサンド、従来のCNCのスラッシュ、コマンドラインからのスペース、Cookie文字列からのセミコロンで再生できる区切り文字で区切られた1つ以上の部分で構成され、さて、ヒープに-垂直線;-)



各「ピース」は、意味そのものと、その前にあるパスで構成されています。 パスが空の場合があります。 パスの各要素の後には、特別な区切り記号が必要です。これは、通常のクエリ文字列でよく知られている等号、JSONでのコロン、およびHTMLフォームで便利なアンダースコアです(送信中にエンコードされないため)。



値とパスの要素は、URI仕様に従ってパーセントでエンコードする必要があります。 ただし、パーサーにとって重要なのは上記の特殊文字のみです。 残りを選別するかどうかは、hiqus文字列がどこでどのように使用されるかによって異なります。



パス要素は空の文字列にすることができ、代わりに自動的に生成された番号が使用されます。 たとえば、「a == 1」は、解析時の「a = 0 = 1」と同等です。



パスに要素が1つしかなく、その要素が空であっても、その後に置かれるセパレータは省略できます。 たとえば、「= blogs / = webstandards」は「blogs / webstandards」と同等です。



「Pieces」はターゲットツリーに順番に追加されます。これにより、値や、以前の値のサブツリーさえも上書きできます。 たとえば、「a = b = 1 / a = 1」は「a = 1」と同等です。



このようなcncがあるとします:/ブログ/ webstandards / 92300 /

hiqusとして解析すると、{'0': 'blogs'、 '1': 'webstandarts'、 '2': '92300'}のようなJSON表現のオブジェクトが得られます



フォームを送信し、次のクエリ文字列を受け取ったとします:q = hiqus&target_type = blogs&target_subtype = offtopic

解析の結果は次のようになります:{q: 'hiqus'、target:{type: 'blogs'、subtype: 'offtopic'}}



次のパラメーターを渡すことにより、コンソールからスクリプトを呼び出したとします:list users sex = female limit = 100

解析後、{'0': 'list'、 '1': 'users'、 'sex': 'female'、limit: '100'}を取得します



このようなクッキーを取得しましょう:sid = 1234; login = tenshi

解凍して取得:{sid: '1234'、login: 'tenshi'}



JavaScriptリファレンス実装

var Hiqus= new function (){<br><br>Version: 1<br>Description: "parse, serialize and merge any 'HIerarhical QUery String'" <br>License: 'public domain' <br><br>Implementation:<br><br> var sepHiqusList= '/|; &' <br> var sepPathList= '=:_' <br><br> var sepHiqusDefault= sepHiqusList.charAt(0)<br> var sepPathDefault= sepPathList.charAt(0)<br><br> var sepHiqusRegexp= RegExp( '[' + sepHiqusList + ']' , 'g' )<br> var sepPathRegexp= RegExp( '[' + sepPathList + ']' , 'g' )<br><br> var encode= function ( str ){<br> return encodeURIComponent( str ).split( '_' ).join( '%5F' )<br>}<br> var decode= function ( str ){<br> return decodeURIComponent( str )<br>}<br><br> var splitHiqus= function ( str ){<br> return str.split( sepHiqusRegexp )<br>}<br> var splitPath= function ( str ){<br> var path= String( str ).split( sepPathRegexp )<br> for ( var j= path.length - 1; j >= 0; --j ) path[ j ]= decode( path[ j ] )<br> return path<br>}<br><br> var get= function ( ){<br> var obj= this <br> for ( var i= 0, len= arguments.length; i < len; ++i ){<br> var name= arguments[ i ]<br> if ( !name ) throw new Error( 'name is empty' )<br> obj= obj[ name ]<br> if ( typeof obj !== 'object' ) return obj<br> }<br> return obj<br>}<br><br> var placin= function ( ){<br> var obj= this <br> for ( var i= 0, len= arguments.length; i < len; ++i ){<br> var name= arguments[ i ]<br> if ( name && Number( name ) != name ){<br> var o= obj[ name ]<br> if (( !o )||( typeof o !== 'object' )) o= obj[ name ]= []<br> } else {<br> var o= []<br> obj.push( o )<br> }<br> obj= o<br> }<br> return obj<br>}<br><br> var put= function ( ){<br> var obj= this <br> var len= arguments.length<br> if ( !len ) return this <br> var val= arguments[ len - 1 ]<br> var key= arguments[ len - 2 ]<br> if ( len > 2 ){<br> var path= []<br> for ( var i= len - 2; i-- ;) path[ i ]= arguments[ i ]<br> obj= placin.apply( obj, path )<br> }<br> if ( typeof val === 'object' ){<br> var v= ( len === 1 ) ? obj : placin.call( obj, key )<br> for ( var i in val ) if ( val.hasOwnProperty( i ) ) put.call( v, i, val[ i ] )<br> } else {<br> val= String( val )<br> if ( !key || Number( key ) == key ) obj.push( val )<br> else obj[ key ]= val<br> }<br> return this <br>}<br><br> var parsin= function ( str ){ <br> var chunks= splitHiqus( str )<br> for ( var i= 0, len= chunks.length; i < len; ++i ){<br> var path= chunks[i]<br> if ( !path ) continue <br> path= splitPath( path )<br> put.apply( this , path )<br> }<br> return this <br>}<br><br> var serialize= function ( prefix, obj ){<br> if ( !obj ) return '' <br> if ( typeof obj !== 'object' ){<br> if ( prefix === sepPathDefault ) prefix= '' <br> return prefix+= encode( obj )<br> }<br> var list= []<br> for ( var key in obj ) if ( obj.hasOwnProperty( key ) ){<br> var k= ( Number( key ) == key ) ? '' : encode( key )<br> var chunk= serialize( prefix + k + sepPathDefault, obj[ key ] )<br> if ( chunk ) list.push( chunk )<br> }<br> return list.join( sepHiqusDefault )<br>}<br><br> var Hiqus= function ( ){<br> var hiqus= ( this instanceof Hiqus ) ? this : new Hiqus<br> var data= placin.call( hiqus, '_data' )<br> for ( var i= 0, len= arguments.length; i < len; ++i ){<br> var arg= arguments[i]<br> if ( arg instanceof Hiqus ) arg= arg._data<br> var invoke= ( Object( arg ) instanceof String ) ? parsin : put<br> invoke.call( data, arg )<br> }<br> return hiqus<br>}<br><br>Hiqus.prototype= new function (){<br><br> this .put= function (){<br> var hiqus= Hiqus( this )<br> put.apply( hiqus._data, arguments )<br> return hiqus<br> }<br> <br> this .get= function ( ){<br> var val= get.apply( this ._data, arguments )<br> if ( typeof val === 'object' ) val= put.call( [], val )<br> return val<br> }<br> <br> this .sub= function (){<br> var hiqus= Hiqus()<br> var val= get.apply( this ._data, arguments )<br> if ( typeof val !== 'object' ) val= [ val ]<br> hiqus._data= val<br> return hiqus<br> }<br><br> this .toString = function (){<br> var str= serialize( '' , this ._data )<br> this .toString= function (){ return str }<br> return str<br> }<br><br>}<br><br>Export: return Hiqus<br><br>Usage:<br><br>alert(<br> Hiqus<br> ( Hiqus( '| a:b:c:1 / a:b: ; a:b::c & a=b__d' )<br> .sub( 'a' , 'b' )<br> .put( [ 'e' , 'f' ] )<br> , 'g/h' <br> )<br> .get( 4 )<br>) // alerts 'g' <br><br>}





HiqusオブジェクトはImmutableパターンを実装し、コンストラクターを介して必要なデータを受け入れます。 次のいずれかのタイプの任意の数のパラメーターを使用できます。
  1. ひも 解析されてツリーに追加されます。
  2. Hiqusオブジェクト。 そのデータはツリーに隣接します。
  3. JSON Hiqusオブジェクトに似ています。
hiqusオブジェクトのメソッド:
  1. put-元のコピーであるが、特定のパスに沿って指定された値を持つ新しいオブジェクトを返します。 Hiqus()。Put({user:{name: 'Nick'}})はHiqus()と同等です。Put( 'user'、{name: 'Nick'})とHiqus()。Put( 'user'、 'と同等です名前 '、' Nick ')
  2. get-特定のパスの値のコピーを返します。 Hiqus()。Get( 'user'、 'name')は不確実性を返し、Hiqus( 'Nick; John')。Get()は['Nick'、 'John']を返します
  3. sub-特定のパスの値に基づいて新しいオブジェクトを作成します。 Hiqus( 'users :: Nick | users :: John')。Sub( 'users')はHiqus( 'Nick; John')と同等です
  4. toString-スラッシュと等号を区切り文字として使用して文字列に変換します。 シリアル化の結果はキャッシュされます。

テスト

;( function ( x, y ){<br> if ( '' + x == y ) return arguments.callee<br> console.log( x, y )<br> throw new Error( 'fail test: [ ' + x + ' ]!=[ ' + y + ' ]' )<br>})<br><br>( Hiqus( ), '' )<br>( Hiqus( {} ), '' )<br>( Hiqus( [] ), '' )<br>( Hiqus( [1] ), '1' )<br>( Hiqus( { '' :1} ), '1' )<br>( Hiqus( { '' :{ '' :1}} ), '==1' )<br>( Hiqus( [1,2] ), '1/2' )<br>( Hiqus( {1:2} ), '2' )<br>( Hiqus( {a:1} ), 'a=1' )<br>( Hiqus( { 'a_b' :1} ), 'a%5Fb=1' )<br>( Hiqus( {a:{b:1}} ), 'a=b=1' )<br>( Hiqus( {a:1,b:2} ), 'a=1/b=2' )<br>( Hiqus( {a:1},{b:2} ), 'a=1/b=2' )<br>( Hiqus( {a:1}, 'b:2' ), 'a=1/b=2' )<br>( Hiqus( {a:1},{b:2} ), new Hiqus( {a:1},{b:2} ) )<br>( Hiqus( Hiqus({a:1}), Hiqus({b:2}) ), 'a=1/b=2' )<br><br>( Hiqus( '' ), '' )<br>( Hiqus( 'a' ), 'a' )<br>( Hiqus( '=a' ), 'a' )<br>( Hiqus( '==1' ), '==1' )<br>( Hiqus( 'a=1' ), 'a=1' )<br>( Hiqus( 'a:1' ), 'a=1' )<br>( Hiqus( 'a_1' ), 'a=1' )<br>( Hiqus( 'a=b=1' ), 'a=b=1' )<br>( Hiqus( 'a=1/b=2' ), 'a=1/b=2' )<br>( Hiqus( 'a=1;b=2' ), 'a=1/b=2' )<br>( Hiqus( 'a=1 b=2' ), 'a=1/b=2' )<br>( Hiqus( 'a=1&b=2' ), 'a=1/b=2' )<br>( Hiqus( 'a=1|b=2' ), 'a=1/b=2' )<br><br>( Hiqus( '1/2' ).get(), '1,2' )<br>( Hiqus( 'a=1/b=2' ).get( 'a' ), '1' )<br>( Hiqus( 'a=1=2/b=2=3' ).get( 'b' ,'0'), '3' )<br>( ( ( a= Hiqus( 'a=1/b=2' ) ).get( 'a' ), a ), 'a=1/b=2' )<br><br>( Hiqus( 'a=1/b=2' ).sub(), 'a=1/b=2' )<br>( Hiqus( 'a=b=1/a=c=2/d=3' ).sub( 'a' ), 'b=1/c=2' )<br>( Hiqus( 'a=b==1/a=b==2' ).sub( 'a' , 'b' ), '1/2' )<br>( ( a= Hiqus( 'a=1/b=2' ) ).sub( 'a' ) && a, 'a=1/b=2' )<br><br>( Hiqus( 'a=1' ).put( {b:2} ), 'a=1/b=2' )<br>( Hiqus( 'a=1' ).put( 'a' , {b:2} ), 'a=b=2' )<br>( ( a= Hiqus( 'a=1' ) ).put( 'b=2' ) && a, 'a=1' )<br>;






All Articles