ember.jsember-data

Ember Data - How to deserialize model.serialize()?


In Ember Data 3.24, if you do

foo = record.serialize()

how can you reverse the process? i.e. deserialize the JS object in foo and update the record?


Solution

  • The reverse process for Model.serialize() is Store.pushPayload():

    // push some sample data into Ember Data's store
    this.store.push({
      data: {
        type: 'post',
        id: '1',
        attributes: {
          title: 'foo',
        },
      },
    });
    
    // get the record    
    const record = this.store.peekRecord('post', '1');
    
    // serialize the record
    const serialized = record.serialize({ includeId: true });
    
    // manipulate the record to see the update
    // this assumes that the application uses the default JSON:API serializer
    serialized.data.attributes.title = 'bar';
    
    // push the new state into the store again
    this.store.pushPayload('post', serialized);
    
    // verify that the update is reflected in Ember Data's store
    console.log(record.title); // "bar"
    

    Please note that Store.pushPayload() does not return the records which are were in the payload.

    If you want to push a record into the store and get that one, you can use Store.push(). But that one expects a normalized JSON:API document following the internal conventions of Ember Data.

    A payload could be normalized to a JSON:API document following the internal conventions of Ember Data with the Serializer.normalizeResponse() method. But it has a complex arguments interface, which does not fit well with the day-to-day usage of Ember Data.

    // manipulate serialized state
    serialized.data.attributes.title = 'baz';
    
    // normalize the payload to JSON:API document following Ember Data's conventions
    const store = this.store;
    const model = this.store.modelFor('post');
    const normalized = this.store.serializerFor('post').normalizeResponse(this.store, PostModel, serialized, undefined, 'findRecord');
    
    // push it into the store
    const result = this.store.push(normalized);
    
    // verify that store has been updated
    console.log(record.title); // "baz"
    
    // Store.push() returns the record
    console.log(record === result);
    

    If only dealing with one record and not needing a fully reverse function, you may also use Store.normalize(). Assuming that your application uses JSON:API serializer the payload could also be normalized like this:

    const normalized = this.store.normalize('post', serialized.data);
    this.store.push(normalized);