最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Redux normalizr - nested API responses - Stack Overflow

programmeradmin2浏览0评论

How can I use normalizr to deal with nested standardised JSON API responses that are key via the { data: ... } standard?

For example a Book

{
    data: {
        title: 'Lord of the Rings',
        pages: 9250,
        publisher: {
            data:  {
                name: 'HarperCollins LLC',
                address: 'Big building next to the river',
                city: 'Amsterdam'
            },
        },
        author: {
            data: {
                name: 'J.R.R Tolkien',
                country: 'UK',
                age: 124,
            }
        }
    }
}   

How would I design schemas to deal with the nested data key?

How can I use normalizr to deal with nested standardised JSON API responses that are key via the { data: ... } standard?

For example a Book

{
    data: {
        title: 'Lord of the Rings',
        pages: 9250,
        publisher: {
            data:  {
                name: 'HarperCollins LLC',
                address: 'Big building next to the river',
                city: 'Amsterdam'
            },
        },
        author: {
            data: {
                name: 'J.R.R Tolkien',
                country: 'UK',
                age: 124,
            }
        }
    }
}   

How would I design schemas to deal with the nested data key?

Share Improve this question edited Jul 4, 2016 at 14:19 AndrewMcLagan asked Jul 1, 2016 at 13:53 AndrewMcLaganAndrewMcLagan 14k25 gold badges96 silver badges166 bronze badges 2
  • The json which you post doesn't follow the JSONAPI specifications. Quickly, you can not nest other resources in the main one, but for including other resources in the payload you've to use the specific key include. In the main resource you can send only a limited set of information about the relationships between itself and other resources under the key relationships . – NickGnd Commented Jul 4, 2016 at 15:55
  • Your right, I will update the question – AndrewMcLagan Commented Jul 4, 2016 at 21:02
Add a ment  | 

2 Answers 2

Reset to default 6

For each entity in your response, you should create it's own schema.

In your example, we have three entities - books, authors and publishers:

// schemas.js
import { Schema } from 'normalizr';

const bookSchema = new Schema('book');
const publisherSchema = new Schema('publisher');
const authorSchema = new Schema('author');

If some entity contains nested data which should be normalized, we need to use define method of it schema.This method accepts an object with nesting rules.

If we need to normalize publisher and author props of book entity, we should pass an object to define function with same structure as our response:

// schemas.js
bookSchema.define({
  data: {
    publisher: publisherSchema,
    author: authorSchema
  }
});

Now we can normalize our response:

import { normalize } from 'normalizr';
import { bookSchema } from './schemas.js';

const response = {
    data: {
        title: 'Lord of the Rings',
        pages: 9250,
        publisher: {
            data:  {
                name: 'HarperCollins LLC',
                address: 'Big building next to the river',
                city: 'Amsterdam'
            },
        },
        author: {
            data: {
                name: 'J.R.R Tolkien',
                country: 'UK',
                age: 124,
            }
        }
    }
}

const data = normalize(response, bookSchema);

I believe what you're after is the use of the assignEntity function which can be passed in the options of normalize. In this instance it lets us, where appropriate, filter out the redundant data properties and go straight to the values underneath.

Effectively assignEntity let's you control how each key of data is normalized. Take a look here for a little more on how it works.

I put this together as a demonstration, take a look: http://requirebin./?gist=b7d89679202a202d72c7eee24f5408b6. Here's a snippet:

book.define({
  data: {
    publisher: publisher,
    author: author,
    characters: normalizr.arrayOf(character)
  }}
);

publisher.define({
  data: {
    country: country
  }
});

const result = normalizr.normalize(response, book, { assignEntity: function (output, key, value, input) {
  if (key === 'data') {
    Object.keys(value).forEach(function(d){
      output[d] = value[d];
    })
  } else {
    output[key] = value;
  }
}});

Also see in particular Ln 29, where the array of characters has some objects with the information nested within data and some without. All are normalized correctly.

I also added some parts to show how it works with arrays and deeply nested data, see the country model within publisher.

With the data provided you will need a slug due to the absence of id's, which each schema also contains in the example.

Normalizr is fantastic, I hope that helps explain a little more about it :)

发布评论

评论列表(0)

  1. 暂无评论