【问题标题】:rearranging JSON with ramda.js - lens based on sibling element?使用 ramda.js 重新排列 JSON - 基于兄弟元素的镜头?
【发布时间】:2017-10-03 03:21:14
【问题描述】:

这是我的数据结构(缩写,你可以跳过这个,直到你在下面找到我问题的核心):

  var data = {
  jsonapi: { version: '1.0' },
  data: {
    type: 'mobile_screens',
    id: '1',
    attributes: { title: 'Watch' },
    relationships: {
      mobile_screen_components: {
        data: [
          { type: 'mobile_screen_components', id: '1_1' },
          { type: 'mobile_screen_components', id: '1_2' },
        ],
      },
    },
  },
  included: [
    {
      type: 'videos',
      id: '5590720024001',
      attributes: {
        thumbnail: {
          width: 1280,
          url:
            'http://media2.XXXXX.com/BrightCove/694940094001/2017/09/27/694940094001_5590729403001_5590720024001-vs.jpg?pubId=694940094001',
          height: 720,
        },
        start_air_date: '2017-09-27T16:32:00.000Z',
        streams: [
          {
            url:
              'http://XXXXX-f.akamaihd.net/i/BrightCove/694940094001/2017/09/27/694940094001_55907,27023001_5590720024001,30873001_5590720024001,32416001_5590720024001,32423001_5590720024001,32792001_5590720024001,32896001_5590720024001,.mp4.csmil/master.m3u8',
            mime_type: 'MP4',
          },
        ],
        last_modified_date: '2017-09-27T16:50:13.471Z',
        description: 'House Republicans renew call amid fresh Comey concerns',
      },
    },
    {
      type: 'videos',
      id: '5590670324001',
      attributes: {
        ...
      },
    },
    {
      type: 'videos',
      id: '5590665282001',
      attributes: {
        ...
      },
    },
    {
      id: '20fb845a-72ad-4d5f-a27a-c01efd857f76',
      type: 'articles',
      attributes: {
        fn__legacy_type: 'articles',
        title: 'Restaurant plans ginormous site near Wall Street, Ground Zero',
        fn__media_tags: ['business'],
        last_published_date: '2017-09-20T18:20:29.526Z',
        thumbnail: {
          image: {
            url:
              'https://secure.media.foxnews.com/BrightCove/990505083001/990505083001/2017/09/13/990505083001_5575086468001_5574853539001-vs.jpg?pubId=694940094001',
          },
        },
      },
      relationships: {
        components_relationships: {
          data: [
            {
              id: 'article_id_7',
              type: 'videos',
            },
            {
              id: 'article_id_8',
              type: 'videos',
            },
          ],
        },
      },
    },
    {
      id: 'e6e327ec-ebb2-4220-a391-41f798e654f7',
      type: 'articles',
      attributes: {
        ...
      },
      relationships: {
        ...
      },
    },
    {
      type: 'mobile_screen_components',
      id: '1_1',
      attributes: { display_type: 'shelf', title: 'Featured Playlist' },
      relationships: {
        videos: {
          data: [
            [
              { type: 'videos', id: '5590720024001' },
              { type: 'videos', id: '5590670324001' },
              { type: 'videos', id: '5590665282001' },
              {
                id: '20fb845a-72ad-4d5f-a27a-c01efd857f76',
                type: 'articles',
              },
              {
                id: 'e6e327ec-ebb2-4220-a391-41f798e654f7',
                type: 'articles',
              },
          ],
        },
        articles: {
          data: [
              {
                id: '20fb845a-72ad-4d5f-a27a-c01efd857f76',
                type: 'articles',
              },
              {
                id: 'e6e327ec-ebb2-4220-a391-41f798e654f7',
                type: 'articles',
              },
          ],
        }
      },
    },
    {
      type: 'videos',
      id: '1241186546001',
      attributes: {
        ...
      },
    },
    {
      type: 'videos',
      id: '1251429410001',
      attributes: {
        ...
      },
    },
    {
      type: 'mobile_screen_components',
      id: '1_2',
      attributes: { display_type: 'shelf', title: 'Live TV' },
      relationships: {
        videos: {
          data: [
            { type: 'videos', id: '1241186546001' },
            { type: 'videos', id: '1251429410001' },
          ],
        },
      },
    },
    {
      type: 'videos',
      id: '2013931500001',
      attributes: {
        ...
      },

    },
    {
      type: 'mobile_screen_components',
      id: '1_3',
      attributes: { display_type: 'shelf', title: 'Live Streams' },
      relationships: {
        videos: {
          data: [{ type: 'videos', id: '2013931500001' }],
        },
      },
    },
  ],
};

对于included 数组中的每个对象,我想检查它是否具有“mobile_screen_components”的type。如果是这样,我想获取该父对象的 relationship 属性中的所有对象(例如 videosarticlesshows 等)并获取每个相应的 data 数组。最后,所有这些数组将被连接起来,并放在一个新的data 数组下,该数组将是items 数组的一个属性,现在是原始对象的唯一属性。

也就是说

{
      type: 'mobile_screen_components',
      id: '1_1',
      attributes: { display_type: 'shelf', title: 'Featured Playlist' },
      relationships: {
        videos: {
          data: [
            [
              { type: 'videos', id: '5590720024001' },
              { type: 'videos', id: '5590670324001' },
              { type: 'videos', id: '5590665282001' }
          ]
        },
        articles: {
          data: [
              {
                id: '20fb845a-72ad-4d5f-a27a-c01efd857f76',
                type: 'articles',
              },
              {
                id: 'e6e327ec-ebb2-4220-a391-41f798e654f7',
                type: 'articles',
              },
          ],
        }
      },
    }

会变成

{
      type: 'mobile_screen_components',
      id: '1_1',
      attributes: { display_type: 'shelf', title: 'Featured Playlist' },
      relationships: {
        items: {
          data: [
            [
              { type: 'videos', id: '5590720024001' },
              { type: 'videos', id: '5590670324001' },
              { type: 'videos', id: '5590665282001' },
              {
                id: '20fb845a-72ad-4d5f-a27a-c01efd857f76',
                type: 'articles',
              },
              {
                id: 'e6e327ec-ebb2-4220-a391-41f798e654f7',
                type: 'articles',
              },
            ],
          ],
        },
      },
    }

我想使用一个镜头来返回整个结构,只应用这个转换。我最初的尝试不起作用:

const getMCRel = (type, rels) => {
  if (type === 'mobile_screen_components' ) {
    return rels
  }
  return undefined
} 
const findMCRel = R.compose(getMCRel, R.props(['type','relationships']));
const rLens = R.lens(findMCRel, R.assoc('relationships'));
const itemsWrapper = (arr) => ({"items": arr});
const result = R.map(R.over(rLens,R.compose(itemsWrapper, R.values)),data.included)

【问题讨论】:

标签: arrays json functional-programming json-api ramda.js


【解决方案1】:

这并不能完全解决问题,但是对于“mobile_screen_components”部分的转换,您可以使用以下内容:

const simplify = over(
  lensProp('relationships'), 
  pipe(pluck('data'), values, flatten, objOf('data'), objOf('items'))
)

simplify(stuff)

您可以在 Ramda REPL 中看到这一点。

要测试您的商品是否属于正确类型,您只需使用:

propEq('type', 'mobile_screen_component')

但是您的要求对我来说还不够清楚,我不知道您是否想reject 那些不属于正确类型的人,或者您是否想map 并仅应用该功能when 这个谓词是正确的。

更新

尝试满足您的全部要求,据我所知,您可以尝试以下方法:

const simplifyAll = over(
  lensProp('included'), 
  map(when(propEq('type', 'mobile_screen_components'), simplify))
)

simplifyAll(data)

这会在许多relationships/items/data 列表中留下很多undefineds。如果你想摆脱它们,你可以更新simplify,在flatten之后添加reject(isNil)

const simplify = over(
  lensProp('relationships'), 
  pipe(pluck('data'), values, flatten, reject(isNil), objOf('data'), objOf('items'))
)

您也可以在 Ramda REPL 中看到这个版本。

最后,如果这是 simplify 函数的唯一用途,您可以将其移动到内联。我建议不要这样做,因为生成的文本墙不太可能像上述版本那样可读。但这是你的决定。

【讨论】:

  • 不完全确定如何将它们组合在一起!现在玩...
  • 想通了! const simplify = over( lensProp('relationships'), pipe(pluck('data'), values, flatten, objOf('data'), objOf('items')) ) R.map( item => { const hasMSC = propEq('type', 'mobile_screen_components'); if(hasMSC(item)) { return simplify(item); } return item; } ,data.included)
猜你喜欢
  • 2015-09-30
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 2011-04-05
  • 2015-01-27
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
相关资源
最近更新 更多