<commit_before>normalizr
=========

Normalizes deeply nested JSON API responses according to a schema for Flux application.  
Kudos to <NAME> for suggesting this approach.

### Sample App

See **[flux-react-router-example](https://github.com/gaearon/flux-react-router-example)**.

### The Problem

* You have a JSON API that returns deeply nested objects;  
* You want to port your app to [Flux](https://github.com/facebook/flux);
* You noticed [it's hard](https://groups.google.com/forum/#!topic/reactjs/jbh50-GJxpg) for Stores to consume data from nested API responses.  

Normalizr takes JSON and a schema and **replaces nested entities with their IDs, gathering all entities in dictionaries**.

For example,

```javascript
[{
  id: 1,
  title: 'Some Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}, {
  id: 2,
  title: 'Other Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}]
```

can be normalized to

```javascript
{
  result: [1, 2],
  entities: {
    articles: {
      1: {
        id: 1,
        title: 'Some Article',
        author: 1
      },
      2: {
        id: 2,
        title: 'Other Article',
        author: 1
      }
    },
    users: {
      1: {
        id: 1,
        name: 'Dan'
      }
    }
  }
}
```

Note the flat structure (all nesting is gone).

### Features

* Entities can be nested inside other entities, objects and arrays;
* Combine entity schemas to express any kind of API response;
* Entities with same IDs are automatically merged (with a warning if they differ);
* Allows using a custom ID attribute (e.g. slug).

### Usage

```javascript
var normalizr = require('normalizr'),
    normalize = normalizr.normalize,
    Schema = normalizr.Schema,
    arrayOf = normalizr.arrayOf;
```

First, define a schema for our entities:

```javascript
var article = new Schema('articles'),
    user = new Schema('users'),
    collection = new Schema('collections');
```

Then we define nesting rules:

```javascript
article.define({
  author: user,
  collections: arrayOf(collection)
});

collection.define({
  curator: user
});
```

Now we can use this schema in our API response handlers:

```javascript
var ServerActionCreators = {

  // These are two different XHR endpoints with different response schemas.
  // We can use the schema objects defined earlier to express both of them:

  receiveArticles: function (response) {
  
    // Passing { articles: arrayOf(article) } as second parameter to normalize()
    // lets it correctly traverse the response tree and gather all entities:
    
    // BEFORE
    // {
    //   articles: [{
    //     id: 1,
    //     title: 'Some Article',
    //     user: {
    //       id: 7,
    //       name: 'Dan',
    //     }
    //   }, ...]
    // }
    //
    // AFTER:
    // {
    //   result: {
    //    articles: [1, 2, ...] // <--- Note how object array turned into ID array
    //   },
    //   entities: {
    //     articles: {
    //       1: { user: 7, ... }, // <--- Same happens for references to other entities in the schema
    //       2: { ... },
    //       ...<commit_msg>Amend the docs (fixes #8)<commit_after>normalizr
=========

Normalizes deeply nested JSON API responses according to a schema for Flux application.  
Kudos to <NAME> for suggesting this approach.

### Sample App

See **[flux-react-router-example](https://github.com/gaearon/flux-react-router-example)**.

### The Problem

* You have a JSON API that returns deeply nested objects;  
* You want to port your app to [Flux](https://github.com/facebook/flux);
* You noticed [it's hard](https://groups.google.com/forum/#!topic/reactjs/jbh50-GJxpg) for Stores to consume data from nested API responses.  

Normalizr takes JSON and a schema and **replaces nested entities with their IDs, gathering all entities in dictionaries**.

For example,

```javascript
[{
  id: 1,
  title: 'Some Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}, {
  id: 2,
  title: 'Other Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}]
```

can be normalized to

```javascript
{
  result: [1, 2],
  entities: {
    articles: {
      1: {
        id: 1,
        title: 'Some Article',
        author: 1
      },
      2: {
        id: 2,
        title: 'Other Article',
        author: 1
      }
    },
    users: {
      1: {
        id: 1,
        name: 'Dan'
      }
    }
  }
}
```

Note the flat structure (all nesting is gone).

### Features

* Entities can be nested inside other entities, objects and arrays;
* Combine entity schemas to express any kind of API response;
* Entities with same IDs are automatically merged (with a warning if they differ);
* Allows using a custom ID attribute (e.g. slug).

### Usage

```javascript
var normalizr = require('normalizr'),
    normalize = normalizr.normalize,
    Schema = normalizr.Schema,
    arrayOf = normalizr.arrayOf;
```

First, define a schema for our entities:

```javascript
var article = new Schema('articles'),
    user = new Schema('users'),
    collection = new Schema('collections');
```

Then we define nesting rules:

```javascript
article.define({
  author: user,
  collections: arrayOf(collection)
});

collection.define({
  curator: user
});
```

Now we can use this schema in our API response handlers:

```javascript
var ServerActionCreators = {

  // These are two different XHR endpoints with different response schemas.
  // We can use the schema objects defined earlier to express both of them:

  receiveArticles: function (response) {
  
    // Passing { articles: arrayOf(article) } as second parameter to normalize()
    // lets it correctly traverse the response tree and gather all entities:
    
    // BEFORE
    // {
    //   articles: [{
    //     id: 1,
    //     title: 'Some Article',
    //     author: {
    //       id: 7,
    //       name: 'Dan',
    //     }
    //   }, ...]
    // }
    //
    // AFTER:
    // {
    //   result: {
    //    articles: [1, 2, ...] // <--- Note how object array turned into ID array
    //   },
    //   entities: {
    //     articles: {
    //       1: { author: 7, ... }, // <--- Same happens for references to other entities in the schema
    //       2: { ... },
    //       ...
{'fraction_non_alphanumeric': 0.136084142394822, 'fraction_numerical': 0.007605177993527508, 'mean_word_length': 2.3284868066774367, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3535129', 'n_tokens_mistral': 1963, 'n_tokens_neox': 1862, 'n_words': 652}