Ruby
Ruby

Reputation: 2909

How to normalize this simple API response using "normalizr"?

I have this response coming from an API ...

{
    "current_page": 1,
    "data": [
        {
            "id": 1,
            "category_id": 1,
            "creator_id": 1,
            "instructor_id": 1,
            "difficulty_id": 1,
            "status_id": 1,
            "title": "hebae",
            "overview": "Course Overview",
            "deleted_at": null,
            "created_at": "2020-01-02 15:16:08",
            "updated_at": "2020-01-02 15:16:08"
        },
        {
            "id": 2,
            "category_id": 1,
            "creator_id": 1,
            "instructor_id": 2,
            "difficulty_id": 1,
            "status_id": 1,
            "title": "update course 1",
            "overview": "Course Overview",
            "deleted_at": null,
            "created_at": "2020-01-02 15:18:40",
            "updated_at": "2020-01-02 15:19:06"
        },
        {
            "id": 3,
            "category_id": 1,
            "creator_id": 1,
            "instructor_id": 1,
            "difficulty_id": 1,
            "status_id": 1,
            "title": "hebaTest",
            "overview": "Course Overview",
            "deleted_at": null,
            "created_at": "2020-01-02 15:24:09",
            "updated_at": "2020-01-02 15:24:09"
        },
        {
            "id": 4,
            "category_id": 2,
            "creator_id": 1,
            "instructor_id": 1,
            "difficulty_id": 1,
            "status_id": 1,
            "title": "hebaTest",
            "overview": "Adile",
            "deleted_at": null,
            "created_at": "2020-01-02 15:25:03",
            "updated_at": "2020-01-02 15:25:03"
        },
        {
            "id": 5,
            "category_id": 2,
            "creator_id": 1,
            "instructor_id": 1,
            "difficulty_id": 1,
            "status_id": 1,
            "title": "hebaTest",
            "overview": "Adile",
            "deleted_at": null,
            "created_at": "2020-01-02 15:33:06",
            "updated_at": "2020-01-02 15:33:06"
        },
        {
            "id": 6,
            "category_id": 1,
            "creator_id": 1,
            "instructor_id": 1,
            "difficulty_id": 1,
            "status_id": 1,
            "title": "Course Title",
            "overview": "Course Overview",
            "deleted_at": null,
            "created_at": "2020-01-05 08:24:56",
            "updated_at": "2020-01-05 08:24:56"
        },
    ],
    "first_page_url": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course?page=1",
    "from": 1,
    "last_page": 2,
    "last_page_url": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course?page=2",
    "next_page_url": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course?page=2",
    "path": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course",
    "per_page": 15,
    "prev_page_url": null,
    "to": 15,
    "total": 29
}

I'm trying to get the "data" array to be defined as "categories" object, and the rest data can stay the same, how to do that with normalizr?

I tried this ...

const { data } = await apiGetAllCategories();

const dataSchema = new schema.Entity("categories");
const coursesSchema = new schema.Entity("info", {
    data: [dataSchema]
});
const normalizedData = normalize(data, coursesSchema);
console.log(normalizedData);

But it always gives me the "info" as undefined, and the "result" as undefined ...

enter image description here

What am I doing wrong here?

Upvotes: 0

Views: 246

Answers (2)

Ruby
Ruby

Reputation: 2909

For anyone interested in how to normalize this response with "normalizr", I figured out where I went wrong, and that normalizr usually looks for and an "id" key at the top level, and if it can't find that you gonna have to provide it, in my case there was no "id" on the top-level object, so I gave it the "per_page" as an id to make it work ...

const dataSchema = new schema.Entity("data");
const coursesSchema = new schema.Entity( "info", 
{ 
    data: [dataSchema]
}, { idAttribute: "per_page" } );

const normalizedData = normalize(data, coursesSchema);

By the way the "answer" provided by @Drew Reese is way simpler and cleaner in this kind of flat object response that I got.

Cheers :)

Upvotes: 2

Drew Reese
Drew Reese

Reputation: 203081

Your data appears to already be in some reduced/normalized form as I don't see any nested, or repeated data structures. I think a simple array::reduce on your data is sufficient for your needs.

// Reduce data array to map [element.id => element]
const dataObject = data.reduce((dataObject, item) => {
  dataObject[item.id] = item;
  return dataObject;
}, {});

const data = [
  {
    id: 1,
    category_id: 1,
    creator_id: 1,
    instructor_id: 1,
    difficulty_id: 1,
    status_id: 1,
    title: "hebae",
    overview: "Course Overview",
    deleted_at: null,
    created_at: "2020-01-02 15:16:08",
    updated_at: "2020-01-02 15:16:08"
  },
  {
    id: 2,
    category_id: 1,
    creator_id: 1,
    instructor_id: 2,
    difficulty_id: 1,
    status_id: 1,
    title: "update course 1",
    overview: "Course Overview",
    deleted_at: null,
    created_at: "2020-01-02 15:18:40",
    updated_at: "2020-01-02 15:19:06"
  },
  {
    id: 3,
    category_id: 1,
    creator_id: 1,
    instructor_id: 1,
    difficulty_id: 1,
    status_id: 1,
    title: "hebaTest",
    overview: "Course Overview",
    deleted_at: null,
    created_at: "2020-01-02 15:24:09",
    updated_at: "2020-01-02 15:24:09"
  },
  {
    id: 4,
    category_id: 2,
    creator_id: 1,
    instructor_id: 1,
    difficulty_id: 1,
    status_id: 1,
    title: "hebaTest",
    overview: "Adile",
    deleted_at: null,
    created_at: "2020-01-02 15:25:03",
    updated_at: "2020-01-02 15:25:03"
  },
  {
    id: 5,
    category_id: 2,
    creator_id: 1,
    instructor_id: 1,
    difficulty_id: 1,
    status_id: 1,
    title: "hebaTest",
    overview: "Adile",
    deleted_at: null,
    created_at: "2020-01-02 15:33:06",
    updated_at: "2020-01-02 15:33:06"
  },
  {
    id: 6,
    category_id: 1,
    creator_id: 1,
    instructor_id: 1,
    difficulty_id: 1,
    status_id: 1,
    title: "Course Title",
    overview: "Course Overview",
    deleted_at: null,
    created_at: "2020-01-05 08:24:56",
    updated_at: "2020-01-05 08:24:56"
  }
];

// Reduce data array to map [element.id => element]
const dataObject = data.reduce((dataObject, item) => {
  dataObject[item.id] = item;
  return dataObject;
}, {});

console.log(dataObject);

Upvotes: 1

Related Questions