Dealing with arbitrary json attributes in a model


#1

Hey there,

I have a JSON endpoint with a meta column - this meta column is the output of a JSONB column in postgres. When querying the endpoint the output looks like this:

    {
      "link_event":{
        "id":65,
        "link_id":1,
        "key":"click",
        "meta":{
          "get":null,
          "post":{
            "post":"posty"
          },
          "header":{
            "header":"heady"
          },
          "timestamp":"2015-02-27T22:05:53.923+00:00"
        },
        "created_at":"2015-02-27T22:05:53.923Z",
        "updated_at":"2015-02-27T22:28:26.161Z"
      }
    }

When I use {{meta}} inside my template I get [object object] as a string. Would it be possible to create an attribute that can hold the contents of this column as a json hash instead of serialising it into a string? Any pointers on how I might build something like that would be much appreciated :smile:

JH


#2

You can create a “raw” attr type and just pass through the json straight through in your model.

So you have a model that looks like this

import DS from 'ember-data';

export default DS.Model.extend({
  foo: DS.attr('raw')
});

And a custom “raw” transform that looks like this

in ember cli save the following in a folder like

app/transforms/raw.js

And define it like below. Note we are just passing the raw serialized json and not doing anything with it.

import DS from 'ember-data';

export default DS.Transform.extend({
  deserialize: function(serialized) {
    return serialized;
  },
  serialize: function(deserialized) {
    return deserialized;
  }
});

One side note about “meta”. It looks like you want to create meta as a normal property in your “link_event” model. I believe in JSON API spec “meta” has a special meaning.

http://jsonapi.org/format/

“meta”: non-standard meta-information about the primary data.

The implication here is that in ember data your “meta” might be handled in a special way. I am not 100% sure though. Would have to try it out. Read more about the metadata handling in ember.

http://emberjs.com/guides/models/handling-metadata/

But if you add the custom raw transform I believe the following model definition would work for you.

// app/models/link-event.js

import DS from 'ember-data';

export default DS.Model.extend({
  linkId: DS.attr('number'),
  key: DS.attr('string'),
  meta: DS.attr('raw'),
  createdAt: DS.attr('date'),
  updatedAt: DS.attr('date')
});

Just note that “meta” property is now opaque and you would need to “know” about the keys when using in your templates. e.g.

{{model.meta.get}}
{{model.meta.post}}
{{model.meta.post.post}}
{{model.meta.header.header}}
{{model.meta.timestamp}}
etc.

Hope that helps.


#3

Hi @eccegordo,

Just wanted to thank you for that answer - it works a treat!

All the best, JH