javascript - 如何使用 Ramda 更新 JSON 中任何级别的键值?

标签 javascript json ramda.js

有没有办法找到一个键的值,它可以出现在任何对象下的任何级别并使用 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>

值得一提的是,只有在保证在目标对象中找到路径的情况下,这些才是有效的镜头,否则行为是不确定的。

关于javascript - 如何使用 Ramda 更新 JSON 中任何级别的键值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51651438/

相关文章:

javascript - 有没有办法让 flexbox 等高列与具有不同字体大小和字体系列的文本的基线字体对齐?

javascript - 为什么 Angular 无法登录到 Firebug 控制台

java - 使用 GSON 反序列化通用类型

javascript - 为什么 Ramda 源码有不止一个 curry 函数,Redux compose 也有?

javascript - RamdaJS : After an object operation my keys are getting re-ordered alphabetically? 是预期的吗?

javascript - 从不解析从 Node+Express API 到 MongoDB 的 HTTP 请求

javascript - React Router 4相对路径

Javascript if else 带有 json 文件

javascript - 从具有特定属性的数组中获取项目并将它们显示在一个 div 上

javascript - Ramda 函数在应用于参数时评估函数的相等性