Building Custom jSon hashes

Hi,

I'm building a web service that will be accessed from a phone.

So what I'm seeing so far is that building json responses seems to be quite limited (but I think I'm just missing something)

Lets say I have users, and they can have different amounts of types of debt. In this case the debt is calculated based on a couple of different things. So in order to calculate debt I need to do some things.

I also might want to return a status message (success/failure) with each json resonse

I know I can do something like: render format.json { :json => {:success => true, :user => @user.as_json } }

I can also overwrite as_json in the user model to customize the output. I want to have more options than that thouse, since overwrite as_json is kind of global. I'm imagining having specialized functions that will return json that has a very different structure than the model itself.

render format.json { :json => {:success => true, :user => @user.json_for_dropdown } } render format.json { :json => {:success => true, :user => @user.json_for_invoice } }

Is this possible? How do I write json_for_X to return json etc? Is there a better way to do this? Are there templates that can be used for json like rendering partials?

Thanks

Joe

pipplo wrote in post #950214:

Hi,

I'm building a web service that will be accessed from a phone.

So what I'm seeing so far is that building json responses seems to be quite limited (but I think I'm just missing something)

Lets say I have users, and they can have different amounts of types of debt. In this case the debt is calculated based on a couple of different things. So in order to calculate debt I need to do some things.

I also might want to return a status message (success/failure) with each json resonse

I know I can do something like: render format.json { :json => {:success => true, :user => @user.as_json } }

I can also overwrite as_json in the user model to customize the output. I want to have more options than that thouse, since overwrite as_json is kind of global.

Overriding (not "overwriting", which means something else) as_json in each model is usually the granularity you want -- there's a canonical JSON representation of a User, valid through the whole application.

I'm imagining having specialized functions that will return json that has a very different structure than the model itself.

render format.json { :json => {:success => true, :user => @user.json_for_dropdown } } render format.json { :json => {:success => true, :user => @user.json_for_invoice } }

Is this possible? How do I write json_for_X to return json etc?

The exact same way you'd write as_json.

But do you really want to? If you want different JSON structures, is your application really trying to tell you that it needs different classes? (Only you can tell this for sure. Just trying to get you asking the right questions.)

Is there a better way to do this? Are there templates that can be used for json like rendering partials?

Sure, you can use a template for rendering JSON just as you can for any other format. Rails doesn't care -- it's all just text.

Thanks

Joe

Best,

Is this possible? How do I write json_for_X to return json etc? Is there a better way to do this? Are there templates that can be used for json like rendering partials?

as long as json_for_X returns something that can be serialized to json (ie strings, numbers, arrays, hashes etc) then rails will take care of the rest.

Fred

Overwriting..I'm not even sure why I wrote that..I know better than that.

I guess in general what I am getting at is that I might want the json to return mutliple objects for a reason or calculated values. I dont have a real example yet. I'm trying to define the interface between a phone app and web service I'm just trying to understand how this works before I get too far in and find out I can't do what I wanted in rails. Hopefully this gives a good idea of what I mean.

Say I want to return a list of a users friends, and the number of times they've been poked. The num_poked isn't a direct field in the user, it's a calculated field in the friend model

Friend Model: ... def num_pokes user_pokes.sum("WHERE userid = x") # this is psuedo code just off the top of my head end ...

Sometimes I want to return an array of user ids, and num_pokes. If I override as_json for friends, I would add a check for option :num_pokes I guess, and then I could call it like this?

render format.json { :json => {:success => true, :user => @user.friends.as_json(:include => [:num_pokes] } }

def as_json(options={})

if options[:num_pokes]     {num_pokes => self.num_pokes} end

end

So that makes some sense, but this seems like it would just get really ugly as you start including and excepting more and more values..which is why I wanted to create a function to do it. This function would also handle returning the standard things like success, errors, etc.

render format.json { :json => return_json_for_friends_list() }

I think this function that I am imagining would belong in the UserHelper and not in the model itself...