如何使用Ramda js规范化对特定结构的Api响应

问题描述 投票:0回答:2

假设我们有来自Api的一些嵌套和非规范化数据,我如何使用Ramda简化响应,以便它可以在前端应用程序中轻松使用。

转换此回复

{
  articles: [
    {
      id: 1,
      title: "Dagon",
      tags: [{ id: 1, name: "old ones" }, { id: 2, name: "short story" }]
    },
    {
      id: 2,
      title: "Azathoth",
      tags: [{ id: 1, name: "old ones" }, { id: 3, name: "novel" }]
    },
    {
      id: 3,
      title: "At the Mountains of Madness",
      tags: [{ id: 4, name: "insanity" }, { id: 3, name: "novel" }]
    }
  ]
}

{
  articles: {
    byId:{
        1: { title: "Dagon", tags: [1, 2] },
        2: { title: "Azathoth", tags: [1, 3] },
        3: { title: "At the Mountains of Madness", tags: [3, 4] }
    },
    allIds:[1,2,3]
  },
  tags: {
        byId:{
        1: "old ones",
        2: "short story",
        3: "novel",
        4: "insanity"
        },
        allIds:[1,2,3,4]
  }
}
javascript ramda.js
2个回答
2
投票

我可能会这样写:

const articles = R.pipe(
  R.prop('articles'),
  R.applySpec({
    allIds: R.pluck('id'),
    byId: R.pipe(
      R.groupBy(R.prop('id')), 
      R.map(
        R.pipe(
          R.head, 
          R.evolve({ tags: R.pluck('id') }), 
          R.dissoc('id'),
        ),
      ),
    ),
  }),
);

const tags = R.pipe(
  R.prop('articles'),
  R.pluck('tags'),
  R.flatten,
  R.uniqBy(R.prop('id')),
  R.applySpec({
    allIds: R.pluck('id'),
    byId: R.pipe(
      R.groupBy(R.prop('id')), 
      R.map(R.path([0, 'name'])),
    ),
  }),
);

const normalize = R.applySpec({ tags, articles });

const data = {
  articles: [
    {
      id: 1,
      title: "Dagon",
      tags: [
        { id: 1, name: "old ones" }, 
        { id: 2, name: "short story" },
      ],
    },
    {
      id: 2,
      title: "Azathoth",
      tags: [
        { id: 1, name: "old ones" },
        { id: 3, name: "novel" },
      ],
    },
    {
      id: 3,
      title: "At the Mountains of Madness",
      tags: [
        { id: 4, name: "insanity" },
        { id: 3, name: "novel" },
      ],
    },
  ],
};

console.log('result', normalize(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

1
投票

这很有趣,因为通常会遇到相反的问题:我已经从我希望在客户端上取消规范化的服务中规范化了数据。我可以看到这是如何产生的,但它与我的经历不同。

我可能会这样写:

const articles = pipe(
  prop('articles'),
  reduce((a, {id, title, tags}) => ({...a, [id]: {title, tags: pluck('id', tags)}}), {})
)

const tags = pipe(
  prop('articles'),
  pluck('tags'),
  flatten,
  reduce((a, {id, name}) => ({...a, [id]: name}), {})
)

const normalize = (resp, as = articles(resp), ts = tags(resp)) => ({
  articles: {byId: as, ids: keys(as)},
  tags: {byId: ts, ids: keys(ts)}
})

const resp = {articles:[{id:1,title:"Dagon",tags:[{id:1,name:"old ones"},{id:2,name:"short story"}]},{id:2,title:"Azathoth",tags:[{id:1,name:"old ones"},{id:3,name:"novel"}]},{id:3,title:"At the Mountains of Madness",tags:[{id:4,name:"insanity"},{id:3,name:"novel"}]}]};

console.log(normalize(resp))
<script src="https://bundle.run/[email protected]"></script><script>
const {pipe, prop, reduce, pluck, flatten, keys} = ramda    </script>

reduce中的tags步骤可以被map(values), fromPairs取代,但这感觉就像一个hack,因为它取决于标签中属性的顺序。

与您请求的输出的一个不同之处在于,我将标记ID保留为文章标记的原始顺序。因此article 3有标签[4, 3]而不是你的[3, 4]。我认为这更有意义,因为标签可能有一些内在的排序,但显然如果你不喜欢它,你可以简单地添加一个sort步骤。

© www.soinside.com 2019 - 2024. All rights reserved.