2016-10-10 38 views
0

JSONは関数を処理できないため、JSONオブジェクトのキーフラグでJSON文字列を評価する必要があります。 JSONデータがObjectフォームのときに変更したいと思います。JavaScriptオブジェクトを再帰的にトラバースし、値をキーで置き換えます。

既知のキーパターンに基づいてキーへのフルパスを与えることができる関数/メソッドをオンラインで見つけることができません。

は、このデータを考える:

{ 
    "js:bindto": "#chart-1", // note the key here 'js:' 
    "point": { 
     "r": 5 
    }, 
    "data": { 
     "x": "x", 
     "xFormat": "%Y", 
     "columns": [ 
      ... 
     ], 
     "colors": { 
      "company": "#ed1b34", 
      "trendline": "#ffffff" 
     } 
    }, 
    "legend": { 
     "show": false 
    }, 
    "axis": { 
     "x": { 
      "padding": { 
       "left": 0 
      }, 
      "type": "timeseries", 
      "tick": { 
       "format": "%Y", 
       "outer": false 
      } 
     }, 
     "y": { 
      "tick": { 
       "outer": false, 
       "js:format": "d3.format(\"$\")" // note the key here 'js:' 
      } 
     } 
    }, 
    "grid": { 
     "lines": { 
      "front": false 
     }, 
     "y": { 
      "lines": [...] 
     } 
    } 
} 

フラグがjs:で始まるキーです。

/js:bindto/axis/y/tick/js:formatのようなパスになると、私はjs:formatを調べます。提案に開放されています。

mutateGraphData<T>(data:T):T { 
    // data here is a parsed JSON string. (an object as shown above) 

    let jsonKeys = this.findKeysInJSON(JSON.stringify(data), "js:"); 

    // jsonKeys = ["js:bindto","js:format"] 
     jsonKeys.map((key:string) => { 
      // find the key in data, then modify the value. (stuck here) 
     // i need the full path to the key so i can change the data property that has the key in question 
     }); 
    }); 
    return data; 
} 

findKeysInJSON<T>(jsonString:string, key:string):Array<T> { 
     let keys = []; 
     if (Boolean(~(jsonString.indexOf(`"${key}`)))) { 
      let regEx = new RegExp(key + "(\\w|\\-)+", "g"); 
      keys = jsonString.match(regEx); 
     } 
     return keys; 
} 

私はいくつかのNPMパッケージの周りされています:

私は私が完全なパスを返すことができます見てきました

何も見てきました私はmodiできるので、問題の鍵私はそのプロパティを変更することができますので、オブジェクト自体に直接作業しないでください。

+0

言語のために 'mutateGraphData (data:T):T'とは何ですか? –

+1

@NinaScholz:TypeScript。 –

答えて

1

Ramdaとすることができます。これは、オブジェクトにマップし、オブジェクトの一部を完全に変更不可能な方法で変更できるようにする関数を組み込んでいます。

RamdaはR.lensPathを提供しています。これにより、オブジェクトを掘り起こし、必要に応じて変更することができます。あなたが望むパターンには従いませんが、lensify機能で素早くパッチを当てることができます。

R.set関数を使用して、渡された値にノードを設定し、渡されたオブジェクトのすべての操作を実行するパイプラインを作成します。

ラムダとレンズで本当にクールなことができます。 livecoding.tvのevilsoftをチェックアウトして、本当に良い概要を確認してください。

const obj={"js:bindto":"#chart-1",point:{r:5},data:{x:"x",xFormat:"%Y",columns:[],colors:{company:"#ed1b34",trendline:"#ffffff"}},legend:{show:!1},axis:{x:{padding:{left:0},type:"timeseries",tick:{format:"%Y",outer:!1}},y:{tick:{outer:!1,"js:format":'d3.format("$")'}}},grid:{lines:{front:!1},y:{lines:[]}}} 
 

 
const lensify = path => R.lensPath(path.split('/')) 
 
// create the property accessors split by/
 
const bindToLens = lensify('js:bindto') 
 
const formatLens = lensify('axis/y/tick/js:format') 
 

 
const modifyObj = R.pipe(
 
    R.set(bindToLens, 'dis be bind'), 
 
    R.set(formatLens, 'I been here') 
 
) 
 

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

+0

ブリリアント!...(自分自身:レンズを学ぶ)。 – georg

+0

@georg watch https://www.livecoding.tv/evilsoft/videos/d5BDO-functional-js-レンズそれは沈むのに数時間かかりますが、努力する価値があります。 – synthet1c

+0

便利です。しかし、まだ6行目で、そのプロパティを変更するには完全なパスを知る必要があります。 – Simon

0

周りを見て行った後、私は今、私はパスを解決するためにdottyまたはobject-resolve-pathまたはプレーンオーレsplit('.')を使用することができますJavascript/JSON get path to given subnode? @アダム・rackis

function search(obj, target, path = "") { 
    for (var k in obj) { 
     if (obj.hasOwnProperty(k)) 
      if (k === target) 
       return path + "." + k; 
      else if (typeof obj[k] === "object") { 
       var result = search(obj[k], target, path + "." + k); 
       if (result){ 
        return result; 
       } 
      } 
    } 
    return false; 
} 

search(data,"js:format").slice(1); // returns: axis.y.tick.js:format 
search(data,"js:bindto").slice(1); // returns: js:bindto 

から答えを修正オブジェクトに。

関連する問題