簡體   English   中英

如何使用Ramda更新JSON中任何級別的鍵的值?

[英]How to update value of a key present at any level in a JSON using Ramda?

有沒有辦法找到一個鍵的值,它可以出現在任何對象下的任何級別,並使用Ramda更新它?

例如,

JSON-1

{
  "query": {
    "boundary": {
      "type": "polygon",
      "coordinates": "[[-85.33604,35.055749],[-85.33604,35.07499772909699],[-85.279134,35.07499772909699],[-85.279134,35.055749],[-85.33604,35.055749]]"
    }
}

JSON-2

{
  "query": {
    "nearby": {
      "radius": "30mi",
      "coordinates": "[-121.40019800,38.55378300]"
    }
  }
}

在這兩個JSON中,我想做的事情如下:

query.nearby.coordinates = JSON.parse(query.nearby.coordinates)

query.boundary.coordinates = JSON.parse(query.boundary.coordinates)

具有單一功能。

另一個選擇是定義一個可以處理更新值的鏡頭。

第一種方法將假設存在有限數量的已知路徑,可以找到坐標。

 // Creates a lens that accepts a list of paths and chooses the first // matching path that exists in the target object const somePathLens = paths => toFunctor => target => { const path = R.find( p => R.pathSatisfies(x => x != null, p, target), paths ) return R.map( value => R.assocPath(path, value, target), toFunctor(R.path(path, target)) ) } // R.over can then be used with JSON.parse to parse the first // matching path that is found. const parseCoords = R.over( somePathLens([ ['query', 'boundary', 'coordinates'], ['query', 'nearby', 'coordinates'] ]), JSON.parse ) console.log(parseCoords({ "query": { "boundary": { "type": "polygon", "coordinates": "[[-85.33604,35.055749],[-85.33604,35.07499772909699],[-85.279134,35.07499772909699],[-85.279134,35.055749],[-85.33604,35.055749]]" } } })) console.log(parseCoords({ "query": { "nearby": { "radius": "30mi", "coordinates": "[-121.40019800,38.55378300]" } } })) 
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script> 

如果實際路徑未知且您只需要通過給定鍵找到第一個值,則可以使用第二種方法。

 // Recursively search for the given key in an object, returning the // first matching path if found. const findKeyInPath = (keyToFind, obj) => { const findKeyInPath_ = o => R.has(keyToFind, o) // if found, return this key as the path ? [keyToFind] // otherwise find all keys with objects and recursively // call this function. : R.reduceRight((k, acc) => { // find either the subpath of this key, or the subpath // found in the remaining keys const subPath = R.when(R.isEmpty, _ => acc, findKeyInPath_(o[k])) // if the subpath contains a key, prepend it with the // current key, otherwise return the empty list return R.unless(R.isEmpty, R.prepend(k), subPath) }, [], R.filter(k => R.propIs(Object, k, o), R.keys(o))) return findKeyInPath_(obj) } // Create a lens that recursively searches for the first matching // key within a target object. const someKeyLens = key => toFunctor => target => { // find the path using our new `findKeyInPath` function const path = findKeyInPath(key, target) return R.map( value => R.assocPath(path, value, target), toFunctor(R.path(path, target)) ) } const parseCoords = R.over( someKeyLens('coordinates'), JSON.parse ) console.log(parseCoords({ "query": { "boundary": { "type": "polygon", "coordinates": "[[-85.33604,35.055749],[-85.33604,35.07499772909699],[-85.279134,35.07499772909699],[-85.279134,35.055749],[-85.33604,35.055749]]" } } })) console.log(parseCoords({ "query": { "nearby": { "radius": "30mi", "coordinates": "[-121.40019800,38.55378300]" } } })) 
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script> 

值得一提的是,如果保證在目標對象中找到路徑,則這些只是有效的鏡頭,否則行為是不確定的。

一種方法是遍歷對象樹,並嘗試解析您找到的任何字符串作為JSON。

const parseNestedJSON = R.cond([
   [R.is(String), R.tryCatch(JSON.parse, R.nthArg(1))],
   [R.is(Object), obj => R.map(parseNestedJSON, obj)],
   [R.T, R.identity],
])

請注意,這可能會進行一些不需要的轉換,例如將{foo: '1'}轉換為{foo: 1} (字符串轉換為數字)。

僅定位稱為coordinates嵌套鍵可能更安全:

const parseNestedJSON = R.cond([
    [R.has('coordinates'), R.over(R.lensProp('coordinates'), JSON.parse)],
    [R.is(Object), obj => R.map(parseNestedJSON, obj)],
    [R.T, R.identity],
])

編輯:如果coordinates可能不是json,您也可以在此處使用tryCatch

  [R.has('coordinates'), R.over(R.lensProp('coordinates'), R.tryCatch(JSON.parse, R.nthArg(1)))]

用法:

parseNestedJSON({"nearby": {"coordinates": "[-121.40019800,38.55378300]"}})
=> { nearby: { coordinates: [ -121.400198, 38.553783 ] } }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM